Local 단위에서 호출하여 Remote로 연결된 1개 이상의 Machinge에서 실행되는 함수
Return이 없는 단방향 함수 호출이 특징
RPC는 주로 일시적이거나, 외형적으로 드러나는 Unreliable Gameplay Event에 사용된다.
사운드 재생
Particle 생성
Animation 재생
RPC는 Replicated/ReplicatedUsing 선언이 된 Property의 Replication을 보완하는 중요한 기능이다.
RPC를 호출하려면 다음 2가지 조건이 성립되어야 한다.
Actor나 Actor Component일 것.
RPC를 호출하는 Object가 Replicate되어 있을 것.
마지막으로 RPC를 잘 사용하기 위해서는 Ownership을 잘 이해하는 편이 좋다.
Type
Client
이 Actor에 대해 Client Connection을 소유한 Client에서 실행되는 Unicast RPC
#pragma once
#include "DerivedActor.generated.h"
UCLASS()
class ADerivedActor : public AActor
{
GENERATED_BODY()
public:
// Client RPC Function
UFUNCTION(Client)
void ClientRPC();
}
#include "DerivedActor.h"
ADerivedActor::ADerivedActor(const class FPostConstructInitializeProperties & PCIP) : Super(PCIP)
{
bReplicates = true;
}
void ADerivedActor::ClientRPC_Implementation()
{
// This log will print on every machine that executes this function.
UE_LOG(LogTemp, Log, TEXT("ClientRPC executed."))
}
// Call from client to run on server
ADerivedClientActor* MyDerivedClientActor;
MyDerivedClientActor->ClientRPC();
Execution Matrix
Server
해당 Actor를 소유하는 Client에서 호출하여 Server에서 실행되는 Unicast RPC
#pragma once
#include "DerivedActor.generated.h"
UCLASS()
class ADerivedActor : public AActor
{
GENERATED_BODY()
public:
// Server RPC Function
UFUNCTION(Server)
void ServerRPC();
}
#include "DerivedActor.h"
ADerivedActor::ADerivedActor(const class FPostConstructInitializeProperties & PCIP) : Super(PCIP)
{
bReplicates = true;
}
void ADerivedActor::ServerRPC_Implementation()
{
// This function only executes if ServerRPC_Validate returns true.
// This log will print on every machine that executes this function.
UE_LOG(LogTemp, Log, TEXT("ServerRPC executed."))
}
// Call from client to run on server
ADerivedClientActor* MyDerivedClientActor;
MyDerivedClientActor->ServerRPC();
Execution Matrix
WithValidation
Server RPC에서만 사용할 수 있는 Specifier
Server RPC의 신뢰성과 Network Policy를 구현할 수 있다.
#pragma once
#include "DerivedActor.generated.h"
UCLASS()
class ADerivedActor : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(Replicated)
int32 Health;
int32 MAXHEALTH = 100;
// Server Unreliable RPC Function
UFUNCTION(Server, Unreliable, WithValidation)
void ServerUnreliableRPC(int32 RecoverHealth);
}
Validate 함수는 내부 로직을 통해 RPC 함수를 Server에서 실행할지 여부를 판단한다.
그렇기에 Validate Specifier가 선언된 Server RPC가 실행될 때 Validate 함수가 가장 먼저 호출된다.
만약 Validate 함수에서 false를 반환하면, 해당 Server RPC를 전송한 Client는 Server로부터 연결이 끊긴다.
NetMulticast
Server에서 호출
호출한 Actor와 Relevant한 모든 Client에서 실행되는 Multicast RPC
Client에서도 호출할 수 있으나 Local에서만 동작한다.
#pragma once
#include "DerivedActor.generated.h"
UCLASS()
class ADerivedActor : public AActor
{
GENERATED_BODY()
public:
// Multicast RPC Function
UFUNCTION(NetMulticast)
void MulticastRPC();
}
#include "DerivedActor.h"
ADerivedActor::ADerivedActor(const class FPostConstructInitializeProperties & PCIP) : Super(PCIP)
{
bReplicates = true;
}
void ADerivedActor::MulticastRPC_Implementation()
{
// This log will print on every machine that executes this function.
UE_LOG(LogTemp, Log, TEXT("MulticastRPC executed."))
}
// Call from server to run on server and all relevant clients
ADerviedServerActor* MyDerivedServerActor;
MyDerievedServerActor->MulticastRPC();
Execution Matrix
Reliability
Client/Server/NetMulticast와 같이 사용되는 Specifier
Reliable
RPC 수신자로부터 ACK를 받지 못하면 RPC를 재전송한다.
다음 RPC 호출은 앞선 RPC의 ACK를 수신할 때 실행된다.
순서대로 도착하는 것을 보장해준다.
Unreliable
RPC Packet이 Drop되면 실행되지 않는다.
도착 순서를 보장하지 않는다.
Send Policy
ERemoteFunctionSendPolicy를 지정하여 RPC의 전송 순서를 명시적으로 조정할 수 있다.
enum class ERemoteFunctionSendPolicy
{
/** Unreliable multicast are queued. Everything else is send immediately */
Default,
/** Bunch is send immediately no matter what */
ForceSend,
/** Bunch is queued until next actor replication, no matter what */
ForceQueue,
};
Send Policy 조절은 NetDriver::ProcessRemoteFunctionForChannel을 통해 가능하다.
/** Process a remote function on given actor channel. This is called by ::ProcessRemoteFunction.*/
ENGINE_API void ProcessRemoteFunctionForChannel(
UActorChannel* Ch,
const class FClassNetCache* ClassCache,
const FFieldNetCache* FieldCache,
UObject* TargetObj,
UNetConnection* Connection,
UFunction* Function,
void* Parms,
FOutParmRec* OutParms,
FFrame* Stack,
const bool IsServer,
const ERemoteFunctionSendPolicy SendPolicy = ERemoteFunctionSendPolicy::Default);
void UNetDriver::ProcessRemoteFunctionForChannel(
UActorChannel* Ch,
const FClassNetCache* ClassCache,
const FFieldNetCache* FieldCache,
UObject* TargetObj,
UNetConnection* Connection,
UFunction* Function,
void* Parms,
FOutParmRec* OutParms,
FFrame* Stack,
const bool bIsServer,
const ERemoteFunctionSendPolicy SendPolicy)
{
EProcessRemoteFunctionFlags UnusedFlags = EProcessRemoteFunctionFlags::None;
ProcessRemoteFunctionForChannelPrivate(Ch, ClassCache, FieldCache, TargetObj, Connection, Function, Parms, OutParms, Stack, bIsServer, SendPolicy, UnusedFlags);
}
Default
RPC가 bunch에 직렬화 된다.
Bunch는 다음 Frame 마지막에 NetUpdate에서 전송된다.
ForceSend
RPC가 NetDriver::PostTickDispatch에서 trigger되면 bunch에 즉시 직렬화 되고 Network에 전송된다.
tick의 나머지 부분이 동작하는 도중에 trigger 되면, Default로 동작한다.
이 특별한 RPC 최적화 기법은 아래 조건 하에서 동작한다.
Replication Graph나 Iris를 사용할 때에만 동작한다.
NetWroldTickTime에서 호출된 RPC에서 동작.
수신한 패킷되고 수신한 RPC가 실행된다.
ForceQueue
Network Update이 마무리 될 때 Bandwidth가 남아 있다면 Bunch에 직렬화된다.