[UE5] RepNotify, RPC를 이용한 멀티캐스트

kkado·2024년 7월 1일
0

UE5

목록 보기
45/63
post-thumbnail

용어

Replication

복제

서버-클라이언트의 구조를 가진 게임 플레이 환경에서, 실질적인 게임의 실행은 서버에서만 일어나고 나머지 클라이언트에서는 게임 상태들을 서버로부터 복제받아 미러링하여 사용자의 기기에서 서버 환경을 동기화한다.

따라서 복제는 항상 서버 -> 클라이언트의 방향으로만 발생한다.

Rep Notify

변수가 복제될 때 자동으로 호출되는 함수이다.
ReplicatedUsing UPROPERTY를 통해 서로 바인딩할 수 있다.

RPC

사용자의 입력 등과 같이, 클라이언트 -> 서버의 방향으로 정보가 전달되어야 할 때가 있다. 다른 기기, 예컨대 서버에서 함수를 실행할 수 있도록 하는 함수를 RPC라고 한다.

예를 들어 총을 발사하는 인풋을 클라이언트가 보냈다고 가정할 때 다른 모든 클라이언트에서도 이와 관련한 애니메이션을 비롯한 여러 기능들을 실행해야 한다. 이 때 서버 측에서 실행되는 Server RPC를 호출하고, 그 서버RPC 안에서 전체 클라이언트에 멀티캐스트 되는 Multicast RPC를 재호출할 수 있다.


예시) 재장전 기능 및 애니메이션 복제

재장전 도중 재차 재장전 기능을 실행한다거나 총을 발사할 수 없도록 하기 위해 현재 캐릭터의 state를 나타낼 수 있는 enum class를 만든다.

UENUM(BlueprintType)
enum class ECombatState : uint8
{
	ECS_Unoccupied		UMETA(DisplayName = "Unoccupied"),
	ECS_Reloading		UMETA(DisplayName = "Reloading"),

	ECS_MAX				UMETA(DisplayName = "DefaultMAX")
};

그리고 인풋과 연결된 Reload() 함수는 갖고 있는 총알 수와 ECombatState를 통해 유효성을 검증한 후 server RPC를 호출한다.

void UCombatComponent::Reload()
{
	if (CarriedAmmo > 0 && CombatState != ECombatState::ECS_Reloading)
	{
		ServerReload();
	}
}

재장전이 시작되면 곧장 ECombatStateReloading으로 수정하고 애니메이션 몽타주를 실행한다. 그리고 앞으로의 확장성을 위해 멀티캐스트 RPC를 호출하기보다는 ECombatState를 rep 변수로 만들고, 이에 대한 rep notify 함수를 통해 멀티캐스트로 동작하게끔 하자.

이 rep notify 함수에서는 switch 문을 통해 각 state별로 실행할 동작들을 정의하며, 지금은 간단히 애니메이션 몽타주만 실행하도록 한다.

void UCombatComponent::ServerReload_Implementation()
{
	if (Character == nullptr)
	{
		return;
	}
	CombatState = ECombatState::ECS_Reloading;
	HandleReload();
}

void UCombatComponent::HandleReload()
{
	Character->PlayReloadMontage();
}

void UCombatComponent::OnRep_CombatState()
{
	switch (CombatState)
	{
	case ECombatState::ECS_Reloading:
		HandleReload();
		break;
	}
}

마지막으로 재장전 동작이 끝났을 때 다시 재장전 기능을 호출할 수 있게 하고, 탄약을 갱신하는 등의 기능을 하기 위해 FinishReloading() 함수를 만들고 이를 애니메이션 몽타주에서 notify 할 수 있게 하기 위해 UFUNCTION(BlueprintCallable) 을 명시한다.

void UCombatComponent::FinishReloading()
{
	if (Character == nullptr)
	{
		return;
	}
	if (Character->HasAuthority())
	{
		CombatState = ECombatState::ECS_Unoccupied;
	}
}

재장전이 완료되는 시점, 예컨대 탄창을 다시 총기에 끼워 넣는 애니메이션이 진행되는 시점에 재장전이 완료될 수 있게끔 한다.
해당하는 프레임에 노티파이를 달고, 애니메이션 이벤트 그래프에서 해당 노티파이가 발생했을 때 FinishReloading() 을 실행하도록 블루프린트를 구성한다.

profile
베이비 게임 개발자

0개의 댓글