0. 개요

플레이어 캐릭터가 사망하면, 가장 최근에 저장된 게임을 가져와 재시작하거나 게임을 종료한다.

 

 

1. 플레이어 사망 이후

(1) AuraGameModeBase에서 플레이어 캐릭터 사망 이후 작업

void PlayerDied(ACharacter* DeadCharacter);
void AAuraGameModeBase::PlayerDied(ACharacter* DeadCharacter)
{
    // 저장 오브젝트 불러와 마지막 저장 확인
    ULoadScreenSaveGame* SaveGame = RetrieveInGameSaveData();
    if (IsValid(SaveGame) == false)
       return;

    UGameplayStatics::OpenLevel(DeadCharacter, FName(SaveGame->MapAssetName));
}

현재 게임 인스턴스의 슬롯 이름과 인덱스를 이용하여 저장된 게임을 가져온다.

저장 오브젝트를 이용하여 레벨을 시작한다.

 

 

(2) 체크 포인트에 도달할 때 맵 이름도 저장하기

void ACheckPoint::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)))
       {
          const UWorld* World = GetWorld();
          FString MapName = World->GetMapName();
          MapName.RemoveFromStart(World->StreamingLevelsPrefix);
          
          AuraGM->SaveWorldState(GetWorld(), MapName);
       }
       
       IPlayerInterface::Execute_SaveProgress(OtherActor, PlayerStartTag);
       HandleGlowEffects();
    }
}

체크 포인트를 통해 게임을 저장할 때, 게임 인스턴스가 맵의 이름을 저장할 수 있도록 맵의 이름을 AuraGameModeBase의 SaveWorldState 함수에 전달한다.

 

 

(3) 로드 슬롯에 맵 에셋 이름 저장하기

사망 이후, 저장된 맵에서 시작하기 위해 저장 슬롯에 맵 에셋 이름을 저장하여 관리한다.

 

(3-1) MVVM_LoadSlot에서 맵 에셋 이름을 멤버 변수로 선언

	UPROPERTY()
	FString MapAssetName;

 

 

(3-2) MVVM_LoadScreen에서 새로운 슬롯 생성 시 맵 에셋 이름 저장

void UMVVM_LoadScreen::NewSlotButtonPressed(int32 Slot, const FString& EnteredName)
{
    AAuraGameModeBase* AuraGameMode = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(this));
    if (IsValid(AuraGameMode) == false)
    {
       GEngine->AddOnScreenDebugMessage(1, 15.f, FColor::Magenta, FString("Please switch to Single Player"));
       return;
    }
    
    // 새로운 슬롯 생성
    LoadSlots[Slot]->SetMapName(AuraGameMode->DefaultMapName);
    LoadSlots[Slot]->SetLevel(1);
    LoadSlots[Slot]->SetPlayerName(EnteredName);
    LoadSlots[Slot]->SlotStatus = Taken;
    LoadSlots[Slot]->PlayerStartTag = AuraGameMode->DefaultPlayerStartTag;
    LoadSlots[Slot]->MapAssetName = AuraGameMode->DefaultMap.ToSoftObjectPath().GetAssetName();

 

 

(3-3) AuraGameModeBase에서 슬롯에 데이터 저장 시 슬롯에서 맵 에셋 이름 가져와 저장 오브젝트에 저장

void AAuraGameModeBase::SaveSlotData(UMVVM_LoadSlot* LoadSlot, int32 SlotIndex)
{
	// 이미 게임이 존재하면 데이터 삭제
	if (UGameplayStatics::DoesSaveGameExist(LoadSlot->LoadSlotName, SlotIndex))
	{
		UGameplayStatics::DeleteGameInSlot(LoadSlot->LoadSlotName, SlotIndex);
	}

	// 저장 오브젝트 생성
	USaveGame* SaveGameObject = UGameplayStatics::CreateSaveGameObject(LoadScreenSaveGameClass);

	// 데이터를 집어넣기
	ULoadScreenSaveGame* LoadScreenSaveGame = Cast<ULoadScreenSaveGame>(SaveGameObject);
	LoadScreenSaveGame->PlayerName = LoadSlot->GetPlayerName();
	LoadScreenSaveGame->MapName = LoadSlot->GetMapName();
	LoadScreenSaveGame->SaveSlotStatus = Taken;
	LoadScreenSaveGame->PlayerStartTag = LoadSlot->PlayerStartTag;
	LoadScreenSaveGame->MapAssetName = LoadSlot->MapAssetName;

	// 최종 저장
	UGameplayStatics::SaveGameToSlot(LoadScreenSaveGame, LoadSlot->LoadSlotName, SlotIndex);
}

 

 

(4) AuraCharacter에서 캐릭터 사망 이후 일정 시간 뒤에 저장된 게임 불러오기

 

(4-1) 사망 타이머와 사망 시간 선언

UPROPERTY(EditDefaultsOnly)
float DeathTime = 5.f;

FTimerHandle DeathTimer;

해당하는 시간동안 기다렸다가 FTimerDelegate를 사용하여 게임을 다시 불러올 것이다.

 

 

(4-2) CombatInterface의 Die 함수 오버라이드

	// 전투 인터페이스
	virtual int32 GetCharacterLevel_Implementation() override;
	virtual void Die(const FVector& DeathImpulse) override;
	// 전투 인터페이스 끝

AuraCharacter의 부모인 AuraCharacterBase의 Die 함수는 무기를 디졸브하고, 각종 물리 옵션을 비활성화해 캐릭터를 랙돌로 만든다.

void AAuraCharacter::Die(const FVector& DeathImpulse)
{
    // 랙돌 효과 발생
    Super::Die(DeathImpulse);

    FTimerDelegate DeathTimerDelegate;
    DeathTimerDelegate.BindLambda([this]()
    {
        AAuraGameModeBase* AuraGM = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(this));
        if (AuraGM)
        {
            AuraGM->PlayerDied(this);
        }
    });
    
    // 타이머 설정
    GetWorldTimerManager().SetTimer(DeathTimer, DeathTimerDelegate, DeathTime, false);

    // 카메라 추락 방지
    Camera->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
}

Super의 함수를 호출하게 한 이후, FTimerDelegate에 람다 함수를 바인딩한다.

 

 

 

(5) 사망 불리언을 사용하여 애니메이션 블루프린트 비활성화

AuraCharacterBase의 bDead 불리언은 클라이언트 내에서 이펙트 및 사운드 관리를 위해 사용하는 불리언이다.

UPROPERTY(BlueprintReadOnly)
bool bDead = false;

해당 함수를 블루프린트에서 읽을 수 있게 하고, ABP에서 가져와 변수로 등록하여 애니메이션 상태를 변경한다.

 

(5-1) WBP_Aura 이벤트 그래프

AuraCharacter의 bDead 불리언을 가져와 멤버 변수로 승격한다.

 

 

(5-2) WBP_Aura 애님 그래프

스테이트 에일리어스를 활용하여 bDead 불리언이 True이면 어떤 상태에서든 Dead 상태로 오도록 한다.

Dead 상태에서는 애니메이션이 없다.