본문 바로가기
Lib/Unreal

싱글, 멀티플레이 리스폰 시스템 구현 (C++ 소스코드)

by W00gie 2021. 5. 24.

기본적인 게임구조로 캐릭터의 HP가 존재하고 HP가 0에 다다를경우 캐릭터의 State를 초기화해 

시작지점으로 돌리는 리스폰 시스템이 필요합니다.

UE4 내에 이미 이를 위한 RestartPlayer() 함수가 준비되어 있습니다.

 

https://docs.unrealengine.com/en-US/API/Runtime/Engine/GameFramework/AGameModeBase/RestartPlayer/index.html

 

AGameModeBase::RestartPlayer

Tries to spawn the player's pawn, at the location returned by FindPlayerStart

docs.unrealengine.com

RestartPlayer 함수의 경우 새로운 폰을 스폰하고, 초기스타트 지점에 위치시켜주는데

이를 이용해 플레이어가 죽을 경우 컨트롤러를 해제하고, 새로운 캐릭터폰에 Attach 시키는 과정을 정리해놓았습니다.

아래의 코드의 경우 OnHealthChanged 라는  HP의 변경값을 제어하는 델리게이트 함수 내에

리스폰 코드의 호출문을 넣었습니다.

 

+ 다만 데디케이티드 서버를 이용한 멀티플레이를 목적으로 한 게임의 경우

리스폰에 필요한 플레이어 컨트롤러에 대한 접근방법이 달라 구분이 필요합니다.

 

 

 

싱글플레이 케이스

 

void AHunter_Character::OnHealthChanged(UHunter_HealthComponent* HealthComp1, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{

	//HP가 0아래일 경우
	if (Health <= 0.0f && !SourceDied)
	{
		//죽음 처리
		SourceDied = true;

		GetMovementComponent()->StopMovementImmediately();
		GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
		UE_LOG(LogTemp, Warning, TEXT("Dead"));
		
		DetachFromControllerPendingDestroy();


		//리스폰 시간(7) 동안 타이머 실행
		// RespawnTimer 함수 이후에는 CountDownHasFinished()함수 실행됨 그 이후 리턴
		GetWorldTimerManager().SetTimer(RespawnHandle, this, &AHunter_Character::RespawnTimer, 1.0f, true);
		//리스폰(7초) 후 3초 뒤 액터 제거
		SetLifeSpan(10.0f);
	}

}
Brief : RespawnHandle에 속한 타이머, 7초간의 리스폰타임시 1초마다 호출된다.
Input : RespawnTime
Output : None
*/
void AHunter_Character::RespawnTimer()
{
	RespawnTime = RespawnTime - 1.0f;
	UE_LOG(LogTemp, Warning, TEXT("Remain RTime:%f"), RespawnTime);
	if (RespawnTime < 1)
	{
		GetWorldTimerManager().ClearTimer(RespawnHandle);
		RespawnTimeHasFinished();

	}
}

/*
Brief : ResapwnTimmer()함수가 종료될 경우 플레이어를 리스폰시키는 함수
Input : None
Output : 캐릭터 리스폰
*/
void AHunter_Character::RespawnTimeHasFinished()
{
	GetWorld()->GetAuthGameMode()->RestartPlayer(GetWorld()->GetFirstPlayerController());
}

 

언리얼엔진의 싱글플레이 게임의 경우 클라이언트 내에서 컨트롤러들은 플레이어 인덱스를 참조해 번호가 매겨집니다. 

싱글플레이의 경우 플레이어의 인덱스는 항상 첫번째로 매겨지기 때문에,

Respawn 함수내의 RestartPlayer 실행시 매개변수 필요없이 GetFirstPlyaerController()함수를 사용하면 됩니다.

 

 

 

멀티플레이 케이스

void AHunter_Character::OnHealthChanged(UHunter_HealthComponent* HealthComp1, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{

	//HP가 0아래일 경우
	if (Health <= 0.0f && !SourceDied)
	{
		//죽음 처리
		SourceDied = true;

		GetMovementComponent()->StopMovementImmediately();
		GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
		UE_LOG(LogTemp, Warning, TEXT("Dead"));
		
		//컨트롤러 해제 전 해당 플레이어 컨트롤 포인터 저장
		PController = this->GetController();
		DetachFromControllerPendingDestroy();


		//리스폰 시간(7) 동안 타이머 실행
		// RespawnTimer 함수 이후에는 CountDownHasFinished()함수 실행됨 그 이후 리턴
		GetWorldTimerManager().SetTimer(RespawnHandle, this, &AHunter_Character::RespawnTimer, 1.0f, true);
		//리스폰(7초) 후 3초 뒤 액터 제거
		SetLifeSpan(10.0f);
	}

}
/*
Brief : RespawnHandle에 속한 타이머, 7초간의 리스폰타임시 1초마다 호출된다.
Input : RespawnTime
Output : None
*/
void AHunter_Character::RespawnTimer()
{
	RespawnTime = RespawnTime - 1.0f;
	UE_LOG(LogTemp, Warning, TEXT("Remain RTime:%f"), RespawnTime);
	if (RespawnTime < 1)
	{
		GetWorldTimerManager().ClearTimer(RespawnHandle);
		RespawnTimeHasFinished();

	}
}

/*
Brief : ResapwnTimmer()함수가 종료될 경우 플레이어를 리스폰시키는 함수
Input : None
Output : 캐릭터 리스폰
*/
void AHunter_Character::RespawnTimeHasFinished()
{
	//RespawnProcess();
	GetWorld()->GetAuthGameMode()->RestartPlayer(PController);
	UE_LOG(LogTemp, Warning, TEXT("Respawn"));
}

멀티플레이의 경우 싱글플레이와 달리 플레이어 인덱스 개념이 성립되지 않습니다.

서버는 모든 플레이어들의 컨트롤러를 알고있지만 클라이언트단에서는 타 플레이어 컨트롤러에 접근 불가능합니다.

싱글과 같이  GetFirstPlayerController를 사용할 경우 작동되지않아.

캐릭터액터에 Controller를 해제하기전에 컨트롤러를 변수에 저장하고

Respawn 함수 시 해당 컨트롤러를 RestartPlayer 함수의 매개변수로 활용하면 멀티플레이 환경에서도 정상 작동합니다.

 

많이 부족한 초보개발자입니다.

포스팅 내 잘못된 정보는 적극적으로 피드백 부탁드립니다.

 

 

 

 

'Lib > Unreal' 카테고리의 다른 글

Error: CDO Constructor Failed to Find Blueprint 해결 방법  (0) 2021.04.19