0. 개요

체크 포인트 클래스를 상속받아, 다른 맵으로 이동하는 맵 이동 입구를 만든다.

 

 

1. 맵 이동 입구(Map Entrance)

(1) Checkpoint를 상속받는 C++ 클래스 생성

UCLASS()
class AURA_API AMapEntrance : public ACheckPoint
{
	GENERATED_BODY()

public:
	/* HighlightInterface 오버라이드*/
	virtual void HighlightActor_Implementation() override;
	/* HighlightInterface 끝*/
	
	/* SaveInterface 함수 오버라이드 */
	virtual void LoadActor_Implementation() override;
	/* SaveInterface 오버라이트 끝 */

	UPROPERTY(EditAnywhere)
	TSoftObjectPtr<UWorld> DestinationMap;

	UPROPERTY(EditAnywhere)
	FName DestinationPlayerStartTag;
	
protected:
	virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent,
		AActor* OtherActor, UPrimitiveComponent* OtherComp,
		int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) override;
	
};

- 맵 이동을 위해 다음 맵을 소프트 포인터로 저장

- 맵 이동 후 소환 될 위치를 플레이어 스타트 태그로 저장

 

 

(2) HighlightActor 함수 오버라이드

이 클래스는 체크 포인트 클래스와 다르게 도달 여부와 상관 없이 마우스 오버 시 항상 외곽선을 나타낼 것이다.

void AMapEntrance::HighlightActor_Implementation()
{
	// bReached 여부에 상관 없이 하이라이트
	CheckpointMesh->SetRenderCustomDepth(true);
}

 

 

(3) LoadActor 함수 오버라이드

이 클래스는 체크 포인트 클래스와 다르게 SaveGame 변수인 bReached 변수를 사용하여 빛남 효과를 발생시키지 않을 것이다.

void AMapEntrance::LoadActor_Implementation()
{
	// 아무 것도 하지 않음
}

 

 

(4) 오버랩 콜백 함수 오버라이드

void AMapEntrance::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
                                   UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor->Implements<UPlayerInterface>())
	{
		bReached = true;

		// 월드 상태 저장
		if (AAuraGameModeBase* AuraGM = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(this)))
		{
			// TODO:이동하고자 하는 맵을 저장
			AuraGM->SaveWorldState((GetWorld()));
		}
		
		IPlayerInterface::Execute_SaveProgress(OtherActor, PlayerStartTag);
	}
}

 

 

(4-1) LoadScreenSaveGame 저장 오브젝트에 맵의 실제 이름 변수 생성

	UPROPERTY()
	FString MapName = FString("Default Map Name");
	
	UPROPERTY()
	FString MapAssetName = FString("Default Map Asset Name");

다음 맵의 정보를 가져오기 위해 실제 맵의 이름인 MapAssetName을 정의한다.

 

 

(4-2) AuraGameModeBase에서 맵 이름을 실제 이름으로 꺼내오는 함수 선언

FString GetMapNameFromMapAssetName(const FString& MapAssetName);
FString AAuraGameModeBase::GetMapNameFromMapAssetName(const FString& MapAssetName)
{
	for (auto& Map : Maps)
	{
		if (Map.Value.ToSoftObjectPath().GetAssetName() == MapAssetName)
			return Map.Key;
	}
	return FString();
}

맵들을 순회하여 Asset 이름이 일치하면 해당 Asset의 맵 이름을 내보낸다.

 

 

(4-3) 월드 상태 저장할 때 맵의 이름 할당하기

void AAuraGameModeBase::SaveWorldState(UWorld* World, const FString& DestinationMapAssetName)
{
	// 접두사를 제외한 실제 이름만 가져오기
	FString WorldName = World->GetMapName();
	WorldName.RemoveFromStart(World->StreamingLevelsPrefix);

	UAuraGameInstance* AuraGI = Cast<UAuraGameInstance>(GetGameInstance());
	check(AuraGI);
	
	if (ULoadScreenSaveGame* SaveGame = GetSaveSlotData(AuraGI->LoadSlotName, AuraGI->LoadSlotIndex))
	{
		// 맵의 이름 지정
		if (DestinationMapAssetName != FString(""))
		{
			SaveGame->MapAssetName = DestinationMapAssetName;
			SaveGame->MapName = GetMapNameFromMapAssetName(DestinationMapAssetName);
		}

 

 

(4-4) MapEntrance 클래스의 OnSphereOverlap에서 목적지 맵을 저장 후 이동하기

void AMapEntrance::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
                                   UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor->Implements<UPlayerInterface>())
	{
		bReached = true;

		// 월드 상태 저장
		if (AAuraGameModeBase* AuraGM = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(this)))
		{
			// 목적지 맵의 상태를 저장
			AuraGM->SaveWorldState(GetWorld(), DestinationMap.ToSoftObjectPath().GetAssetName());
		}
		IPlayerInterface::Execute_SaveProgress(OtherActor, PlayerStartTag);
        // 맵 이동
		UGameplayStatics::OpenLevelBySoftObjectPtr(this, DestinationMap);
	}
}

 

 

(5) 던전 2 맵 생성

던전 1을 복제하여 던전 2를 만들고, 플레이어 스타트와 체크 포인트의 플레이어 스타트 태그를 지정한다.

 

 

(6) BP_AuraGameMode에 맵 추가

Maps 배열에 던전 2를 추가한다.

 

 

(7) 맵에 추가한 맵 입구 액터에 목적지 정보 입력