본문 바로가기

언리얼러닝/C++스크립트게임개발

네트워크 멀티플레이어 게임 만들기 - RPC

게임 Pangaea를 멀티플레이어 게임으로 만들려면 다음과 같은 작업을 수행해야 한다.

RPC로 플레이어 공격 알려주기

복제를 통행 클라이언트와 액터 변수 동기화하기

RepNotify를 통해 캐릭터의 체력바 업데이트 하기

서버에서 타격 처리학

 서버 측면에서 파이어볼 생성하기

 

RPC로 플레이어 공격 알려주기

Server Rpc ; 클라이언트에서 호출되며 서버에서 실행된다.

Client RPC : 서버에서 호출되며 수신되는 액터를 가진 클라이언트에서 실행된다.

NetMuticast RPC : 서버에서 호출되며 모든 클라이언트뿐만 아니라 서버 자체에서 실행된다.

reliable 도는 unrelable tag를 붙여 신회도를 정할수 있다. 네트워크의 성능향상을 위해서다

RPC함수는 UFUNCTION 매크로에 태그될 수 있다. 여기서는 RPC 유형과 신뢰성을 정할수 있다.

 

멀티플레이어게임에서 싱크를 맞추려면 

클라이언트 사이트에서 플레이어가 공격명령을 입력하면 APlayerAvatar가 Server RPC(Attack_RPC())를 호출해 서버에 해당 액션이 발생했음을 알려줘야 한다.

서버사이드에서 공격 메시지가 수신되면 APangaeaCharacter가 NetMulticast RPC(Attack_Broadcast_RPC())를 호출해 모든 클라이언트에 해당 사실을 알려줘야 한다.

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/remote-procedure-calls-in-unreal-engine

 

PlayerAvatar.h에 Attack_RPC()함수를 선언하고 

	UFUNCTION(Server, Reliable)
	void Attack_RPC();

PlayerAvatar.cpp에 구현한다. 구현시 함수명뒤에 _Implementation()을 추가한다.

void APlayerAvatar::Attack_RPC_Implementation()
{
	Attack_Broadcast_RPC();
}

 

PangaeaCharacter.h에 Attack_Broadcast_RPC()를 선언하고

	UFUNCTION(NetMultiCast, Reliable)
	void Attack_Broadcast_RPC();

PangaeaCharacter.cpp에 구현한다.구현시 함수명뒤에 _Implementation()을 추가한다.

void APangaeaCharacter::Attack_Broadcast_RPC_Implementation()
{
    Attack();
}

클라이언트 사이트에서 Attack 버튼을 클릭했을대 Attack_RPC()함수를 호출하기 위해 APangaeaPlayerController::OnAttackPressed()를 바꿔줘야 한다. PangaeaPlayerController.cpp파일을 다음과 같이 변경한다.

void APangaeaPlayerController::OnAttackPressed()
{
	auto playerAvatar = Cast<APlayerAvatar>(GetPawn());
	if (playerAvatar != nullptr && playerAvatar->CanAttack())
	{
		StopMovement();
		playerAvatar->Attack_RPC();
	}
}

 

앞에서 살펴본 APangaeaCharacter::Attack_Broadcast_RPC()함수의 변경 사항을 기반으로 EnemyController.cpp에서 적 공격에 발생하는 네트워크동기화 문제를 쉽게 해결할수 있다. 적은 서버에서 제어하므로 적이 공격을 수행하려 할때 Attack_Broadcast_RPC()를 호출하도록 만들면 한다.

void AEnemyController::MakeAttackDecision(APawn* targetPawn)
{
	auto enemy = Cast<AEnemy>(GetPawn());
	auto dist = FVector::Dist2D(targetPawn->GetActorLocation(), GetPawn()->GetTargetLocation());

	if (dist <= enemy->AttackRange && enemy->CanAttack())
	{
		StopMovement();
		enemy->Attack_Broadcast_RPC();
	}
}

RPC를 이용해 메시지나 매개변수를 네트워크를 통해 전송할수있지만. 액터이 변수값이 바뀌어 이를 동기화 해야 하는 경우에는 변수 동기화를 처리하기 위해 복제 메커니즘을 활용한다.