Unreal Engine 5 C++ Multiplayer Shooter
RPC (원격 프로시저 호출, Remote Procedure Call)
로컬에서 호출하지만, 다른 원격 컴퓨터에서 실행되는 함수
인자를 전달할 수 있다.
- Actor에서 호출되어야 한다.
(Actor Component에서도 호출할 수 있다.) - Actor는 Replicated 상태여야 한다.
RPC 함수 선언 | 의미 |
UFUNCTION(Server) void ServerRPCFunction(); |
클라이언트가 서버에 RPC를 요청 |
UFUNCTION(Client) void ClientRPCFunction(); |
서버가 클라이언트에 RPC를 요청 |
UFUNCTION(NetMulticast) void MulticastRPCFunction(); |
서버가 서버와 모든 클라이언트에 RPC를 요청 |
서버 RPC는 서버에 존재하는 액터를 요청한 클라이언트가 소유하는 경우에만 실행된다.
클라이언트 RPC는 해당 액터 소유자의 머신에서만 실행된다.
멀티캐스트 RPC는 두 가지로 나뉜다.
- 서버에서 호출될 경우, 서버는 로컬로 실행되고 나머지 모든 클라이언트에서 원격으로 실행된다.
- 클라이언트에서 호출될 경우, 로컬에서만 실행되고 서버에서는 실행되지 않는다.
RPC는 원격 실행을 보장할지에 대한 신뢰성을 설정할 수 있다.
- Unreliable (UDP, 기본값)
원격 실행을 항상 보장하지 않는다. - Reliable (TCP)
원격 실행을 항상 보장하며, 실패 시 다시 RPC를 요청한다.
RPC 함수는 어디서, 어떤 상황에서 호출되는지에 따라 실행되는 곳이 다르다.
현재 서버에서는 무기 획득이 가능하지만, 클라이언트에서는 처리되지 않는 상황이다.
무기 획득에 대한 처리는 서버에서 하고 있기 때문에, 클라이언트는 E 키를 누를 시 서버에 무기 획득 RPC를 보내 무기 획득을 요청하도록 한다.
- 클라이언트가 서버에 요청하는 신뢰성을 보장하는 RPC 함수이다.
독특하게, RPC 함수의 구현부에는 함수 이름에 "_Implementation" 접미사를 꼭 붙여주어야 한다.
이 RPC 함수는 서버 RPC 함수이므로, 클라이언트 호출을 통해 서버에서만 실행된다.
E 키를 눌렀을 때 호출되는 EquipButtonPressed() 함수에서 HasAuthority() 함수를 통해 서버인 경우와 클라이언트인 경우를 나누도록 수정한다.
- 서버는 직접 무기 획득 함수를 실행한다.
- 클라이언트는 서버에 서버 RPC를 호출해 무기 획득을 요청한다.
이제 클라이언트에서도 서버 RPC를 통해 무기를 획득할 수 있게 되었다.
하지만 획득 위젯이 사라지지 않고 있다.
현재 무기 획득 처리는 서버에서 실행되는 이 함수에서 하고 있다.
무기를 소켓에 붙이는 것은 복제되고 있지만, 무기의 상태나 획득 위젯을 숨기는 등 일부는 복제되지 않고 있다.
사실, 이 중 SetOwner() 함수를 통해 소유자는 복제되고 있다.
Actor 클래스 내부에서 소유자인 Owner는 복제 변수이고 OnRep_Owner() 함수를 오버라이드하여 추가 기능을 구현할 수도 있다.
Weapon 액터는 복제된 액터이기 때문에, 변수 리플레케이션과 RepNotify 함수를 통해 값을 동기화하고 콜백 함수를 실행할 수 있다.
무기의 상태를 저장하는 WeaponState 변수를 리플리케이션하고 RepNotify 함수를 지정한다.
GetLifetimeReplicatedProps() 함수를 오버라이드하고 WeaponState 변수를 등록한다.
- 모든 클라이언트에 업데이트를 보낼 것이므로, 조건은 지정하지 않는다.
RepNotify 함수에서는 서버로부터 받은 무기 상태 업데이트 요청을 처리한 후, 상태에 따라 획득 위젯 가시성과 겹침 상태를 변경하도록 한다.
둘 다 위젯이 보이다가 한 클라이언트에서 무기를 획득하니 둘 다 획득 위젯이 사라졌다.
- 복제된 액터인 서버의 무기 상태가 변경되면서 RepNotify 함수가 각 클라이언트에서 실행됐기 때문이다.
하지만 무기를 들고 다른 플레이어게 접근하자, 다른 클라이언트에서는 아직도 획득 위젯이 띄워지는 문제가 있다.
- 각 클라이언트에서는 OnRep_WeaponState() RepNotify 함수를 통해 충돌을 해제했지만, 겹침 확인은 서버에서 처리하고 있기 때문이다.
- 클라이언트는 겹치지 않았지만, 서버에서 다른 플레이어의 무기가 서버에 있는 내 캐릭터와 가까워지면서 겹침 판정이 된 것이다.
서버에서 실행되는 EquipWeapon() 함수에서 무기 상태 변경 RepNotify를 발생시키기 위한 SetWeaponState() 함수와 복제되고 있는 소유자 설정을 제외하고는 SetWeaponState() 함수에서 처리하도록 변경한다.
inline 함수에서 일반 함수로 변경하고, 장착 시 획득 위젯을 숨기고 겹침을 끄도록 구현한다.
정리하면, 서버에서는 무기 장착 시 다음과 같은 과정으로 획득 위젯을 숨기고 겹침을 해제하게 된다.
클라이언트는 서버에 무기 획득 RPC를 요청하고, 그 과정에서 서버로부터 무기 상태 변경 업데이트를 받고 실행된 RepNotify에서 처리한다.
클라이언트가 키를 누르면 서버에 무기 획득 RPC 요청을 보낸다.
서버는 무기 획득 RPC 요청을 처리한다.
무기의 상태가 변경될 때 콜백 함수로 지정했던 RepNotify 함수에서 획득 위젯과 겹침에 대한 처리가 수행된다.
이제 무기를 들고 다른 플에이어 가까이에 가도, 다른 클라이언트에서 획득 위젯이 뜨지 않는다.
- 클라이언트와 서버 모두에서 획득 위젯을 숨기고 겹침을 해제했기 때문이다.
'Unreal Engine > UE5 C++ Multiplayer Shooter' 카테고리의 다른 글
웅크리기 동작 동기화 (0) | 2023.04.05 |
---|---|
무기 장착 애니메이션 동기화 (0) | 2023.04.05 |
무기 장착 (0) | 2023.04.04 |
RepNotify (0) | 2023.04.03 |
변수 리플리케이션 (2) | 2023.04.03 |