한 개의 레벨에 사용할 모든 에셋들을 넣게 된다면 퍼포먼스에 문제가 생길 것이다.
이를 여러 개의 레벨로 나누어 사용할 때마다 불러와서 사용하면 문제를 해결할 수 있을 것이다.
이를 언리얼에서는 레벨 스트리밍 기능을 제공한다.
간단하게 말해서 레벨 스트리밍은 내가 원할 때마다 레벨들을 로드 / 언로드 할 수 있는 기능이다.
이를 이용해 맵 텔레포트를 구현해보자.
먼저 ‘StartMap’이라는 이름으로 기본 라이트만 들어가 있는 맵을 생성하였다.
왼쪽 위 툴바 > 창 > 레벨을 눌러서 레벨 창을 띄운다.
레벨에다가 기본 Floor만 있는 Level1 ~ Level3, 그리고 우리가 시작하게 될 맵 Room을 추가해주고, 겹치지 않게 배치하여 준다.
결과는 다음과 같다.
StartMap에 자손 맵들이 Level1 ~ Level3, Room이 존재하는 것이다.
StartMap은 퍼시스턴트 레벨, 메인 맵이므로 항상 로드되어 있고 나머지 맵들은 원할 때마다 로드 / 언로드가 가능하다.
이제 텔레포트 기능을 하는 C++클래스를 추가하여 상호작용을 할 때마다 이동할 Destination 레벨을 로드해주고, 캐릭터를 이동시킨 뒤 기존에 있던 레벨을 언로드 해주도록 할 것이다.
또한 언리얼 에디터에서 장소 및 목적지 등을 수정하게 하여 여러 레벨에 사용될 수 있도록 할 것이다.
TOTeleport라는 클래스를 생성해서 다음과 같이 작성한다
//TOTeleport.h
#include "Tellours.h"
#include "GameFramework/Actor.h"
#include "TOTeleport.generated.h"
UCLASS()
class TELLOURS_API ATOTeleport : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATOTeleport();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Level 생성 확인
public:
enum EActionId
{
AID_Loading,
};
enum ELinkID
{
LID_Link
};
FLatentActionInfo LatentActionInfo;
UFUNCTION()
void OnStreamLevelLoaded();
// 텔레포트 관련
public:
UFUNCTION()
void Teleport();
private:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Teleport, meta = (AllowPrivateAccess = "true"))
FName CurrentLevel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Teleport, meta = (AllowPrivateAccess = "true"))
FName TeleportDestinationLevel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Teleport, meta = (AllowPrivateAccess = "true"))
FVector TeleportLocation;
};
//TOTeleport.cpp
#include "TOTeleport.h"
#include "TOCharacter.h"
#include "Kismet/GameplayStatics.h"
#include "Components/WidgetComponent.h"
#include "Engine/LevelStreaming.h"
// Sets default values
ATOTeleport::ATOTeleport()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
// Level 기본 설정.
LatentActionInfo.UUID = AID_Loading;
LatentActionInfo.CallbackTarget = this;
LatentActionInfo.Linkage = LID_Link;
LatentActionInfo.ExecutionFunction = FName(TEXT("OnStreamLevelLoaded"));
// 기본 설정.
CurrentLevel = "Room";
TeleportDestinationLevel = "Room";
TeleportLocation = FVector(FVector::ZeroVector);
}
// Called when the game starts or when spawned
void ATOTeleport::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ATOTeleport::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ATOTeleport::Teleport()
{
UGameplayStatics::LoadStreamLevel(this, TeleportDestinationLevel, true, false, LatentActionInfo);
}
void ATOTeleport::OnStreamLevelLoaded()
{
ACharacter* Character = UGameplayStatics::GetPlayerCharacter(this, 0);
Character->SetActorLocation(TeleportLocation);
FTimerHandle WaitHandle;
GetWorld()->GetTimerManager().SetTimer(WaitHandle, FTimerDelegate::CreateLambda([&]()
{
UGameplayStatics::UnloadStreamLevel(this, CurrentLevel, FLatentActionInfo(), false);
}),0.2f, false);
}
이를 설명하면 다음과 같은 과정을 거쳐서 텔레포트 기능을 수행한다.
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Teleport, meta = (AllowPrivateAccess = "true"))
FName CurrentLevel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Teleport, meta = (AllowPrivateAccess = "true"))
FName TeleportDestinationLevel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Teleport, meta = (AllowPrivateAccess = "true"))
FVector TeleportLocation;
현재 레벨과 이동할 레벨, 이동할 위치 등을 언리얼 에디터에서 정할 수 있게 UPROPERTY를 사용해 변수들을 생성해준다.
//TOTeleport.h
enum EActionId
{
AID_Loading,
};
enum ELinkID
{
LID_Link
};
FLatentActionInfo LatentActionInfo;
UFUNCTION()
void OnStreamLevelLoaded();
//TOTeleport.cpp
void ATOTeleport::Teleport()
{
UGameplayStatics::LoadStreamLevel(this, TeleportDestinationLevel, true, false, LatentActionInfo);
}
void ATOTeleport::OnStreamLevelLoaded()
{
ACharacter* Character = UGameplayStatics::GetPlayerCharacter(this, 0);
Character->SetActorLocation(TeleportLocation);
FTimerHandle WaitHandle;
GetWorld()->GetTimerManager().SetTimer(WaitHandle, FTimerDelegate::CreateLambda([&]()
{
UGameplayStatics::UnloadStreamLevel(this, CurrentLevel, FLatentActionInfo(), false);
}),0.2f, false);
}
TeleportDestinationLevel 레벨을 로드할 때 그 레벨의 정보들을 가져온 뒤, 레벨이 로드되었을 시 LatentActionInfo를 통해 OnStreamLevelLoaded 함수를 실행하도록 한다.
로드가 되면 캐릭터의 위치를 이동시키고, 기존에 있던 CurrentLevel를 언로드해준다.
이 때 0.2f초의 딜레이를 주어 기존 레벨에서 수행되고 있던 상호작용이나 다른 실행 내용들을 안정적으로 종료할 수 있게 한다.
언리얼 에디터에서 클래스를 레벨로 꺼내온 뒤, Teleport탭에서 관련 내용들을 수정하여 준다.
이를 통해 레벨 스트리밍 기능을 활용해 텔레포트를 구현하였다.
다음과 같은 결과를 확인할 수 있다.
'UnrealEngine > 공부' 카테고리의 다른 글
[Unreal Engine C++] 진행도에 따른 텔레포트 설정 (1) | 2024.02.27 |
---|---|
[Unreal Engine C++] 현재 레벨 저장 기능의 구현 (0) | 2024.02.27 |
[Unreal Engine C++] 연속 공격의 구현 (0) | 2024.02.27 |
[Unreal Engine C++] SaveData의 구현 (0) | 2024.02.27 |
[Unreal Engine C++] Dash의 이펙트 구현 (0) | 2024.02.27 |
CSE & GAME 개발 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 부탁드립니다!