# Unreal RPC
RPC 在 Unreal 中被广泛运用,是除了 Replication 之外唯二的数据传输方式(另一个是手动压解的收发包模式)。
RPC(Remote Procedure Call)远程过程调用,简单来说就是像执行本地函数一样的调用远程服务接口,简化调用编码复杂度,那么在 Unreal 中具体是如何实现的呢?
# RPC 函数定义
这里以 ServerSetReplicatedTargetData 函数为例,详细了解一下 Unreal 中关于 RPC 的定义:
UFUNCTION(Server, reliable, WithValidation)  | |
void ServerSetReplicatedTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, const FGameplayAbilityTargetDataHandle& ReplicatedTargetDataHandle, FGameplayTag ApplicationTag, FPredictionKey CurrentPredictionKey);  | 
在类声明中,使用 UFUNCTION 宏声明 RPC 函数,并使用 Server 、 Client 或 NetMulticast 关键字指定 RPC 类型。
Server:由客户端调用,但在服务器上执行的函数。Client:由服务器调用,但在特定客户端上执行的函数。NetMulticast:由服务器调用,并在所有连接的客户端上执行的函数。
通过 UHT 生成后的函数定义如下:
GAMEPLAYABILITIES_API UScriptStruct* Z_Construct_UScriptStruct_FGameplayAbilitySpecHandle();  | |
// -------------------------- execFunction -------------------------- | |
DEFINE_FUNCTION(UAbilitySystemComponent::execServerSetReplicatedTargetData)  | |
{ | |
P_GET_STRUCT(FGameplayAbilitySpecHandle,Z_Param_AbilityHandle);  | |
P_GET_STRUCT(FPredictionKey,Z_Param_AbilityOriginalPredictionKey);  | |
P_GET_STRUCT(FGameplayAbilityTargetDataHandle,Z_Param_ReplicatedTargetDataHandle);  | |
P_GET_STRUCT(FGameplayTag,Z_Param_ApplicationTag);  | |
P_GET_STRUCT(FPredictionKey,Z_Param_CurrentPredictionKey);  | |
    P_FINISH; | |
    P_NATIVE_BEGIN; | |
if (!P_THIS->ServerSetReplicatedTargetData_Validate(Z_Param_AbilityHandle,Z_Param_AbilityOriginalPredictionKey,Z_Param_ReplicatedTargetDataHandle,Z_Param_ApplicationTag,Z_Param_CurrentPredictionKey))  | |
    { | |
RPC_ValidateFailed(TEXT("ServerSetReplicatedTargetData_Validate"));  | |
return;  | |
    } | |
P_THIS->ServerSetReplicatedTargetData_Implementation(Z_Param_AbilityHandle,Z_Param_AbilityOriginalPredictionKey,Z_Param_ReplicatedTargetDataHandle,Z_Param_ApplicationTag,Z_Param_CurrentPredictionKey);  | |
    P_NATIVE_END; | |
} | |
struct AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms  | |
{ | |
    FGameplayAbilitySpecHandle AbilityHandle; | |
    FPredictionKey AbilityOriginalPredictionKey; | |
    FGameplayAbilityTargetDataHandle ReplicatedTargetDataHandle; | |
    FGameplayTag ApplicationTag; | |
    FPredictionKey CurrentPredictionKey; | |
};  | |
// -------------------------- Function -------------------------- | |
static FName NAME_UAbilitySystemComponent_ServerSetReplicatedTargetData = FName(TEXT("ServerSetReplicatedTargetData"));  | |
void UAbilitySystemComponent::ServerSetReplicatedTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FGameplayAbilityTargetDataHandle const& ReplicatedTargetDataHandle, FGameplayTag ApplicationTag, FPredictionKey CurrentPredictionKey)  | |
{ | |
    AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms Parms; | |
Parms.AbilityHandle=AbilityHandle;  | |
Parms.AbilityOriginalPredictionKey=AbilityOriginalPredictionKey;  | |
Parms.ReplicatedTargetDataHandle=ReplicatedTargetDataHandle;  | |
Parms.ApplicationTag=ApplicationTag;  | |
Parms.CurrentPredictionKey=CurrentPredictionKey;  | |
ProcessEvent(FindFunctionChecked(NAME_UAbilitySystemComponent_ServerSetReplicatedTargetData),&Parms);  | |
} | |
// 把函数定义注册到 UAbilitySystemComponent 类里 | |
void UAbilitySystemComponent::StaticRegisterNativesUAbilitySystemComponent()  | |
{ | |
UClass* Class = UAbilitySystemComponent::StaticClass();  | |
static const FNameNativePtrPair Funcs[] = {  | |
{ "ServerSetReplicatedTargetData", &UAbilitySystemComponent::execServerSetReplicatedTargetData },  | |
};  | |
FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));  | |
} | |
// -------------------------- Function MetaData -------------------------- | |
struct Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics  | |
{ | |
static const UECodeGen_Private::FStructPropertyParams NewProp_AbilityHandle;  | |
static const UECodeGen_Private::FStructPropertyParams NewProp_AbilityOriginalPredictionKey;  | |
    #if WITH_METADATA | |
static const UECodeGen_Private::FMetaDataPairParam NewProp_ReplicatedTargetDataHandle_MetaData[];  | |
    #endif | |
static const UECodeGen_Private::FStructPropertyParams NewProp_ReplicatedTargetDataHandle;  | |
static const UECodeGen_Private::FStructPropertyParams NewProp_ApplicationTag;  | |
static const UECodeGen_Private::FStructPropertyParams NewProp_CurrentPredictionKey;  | |
static const UECodeGen_Private::FPropertyParamsBase* const PropPointers[];  | |
    #if WITH_METADATA | |
static const UECodeGen_Private::FMetaDataPairParam Function_MetaDataParams[];  | |
    #endif | |
static const UECodeGen_Private::FFunctionParams FuncParams;  | |
};  | |
const UECodeGen_Private::FStructPropertyParams Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_AbilityHandle = { "AbilityHandle", nullptr, (EPropertyFlags)0x0010000000000080, UECodeGen_Private::EPropertyGenFlags::Struct, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms, AbilityHandle), Z_Construct_UScriptStruct_FGameplayAbilitySpecHandle, METADATA_PARAMS(nullptr, 0) }; // 3562347300  | |
const UECodeGen_Private::FStructPropertyParams Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_AbilityOriginalPredictionKey = { "AbilityOriginalPredictionKey", nullptr, (EPropertyFlags)0x0010000000000080, UECodeGen_Private::EPropertyGenFlags::Struct, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms, AbilityOriginalPredictionKey), Z_Construct_UScriptStruct_FPredictionKey, METADATA_PARAMS(nullptr, 0) }; // 2453680625  | |
#if WITH_METADATA | |
const UECodeGen_Private::FMetaDataPairParam Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ReplicatedTargetDataHandle_MetaData[] = {  | |
{ "NativeConst", "" },  | |
};  | |
#endif | |
const UECodeGen_Private::FStructPropertyParams Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ReplicatedTargetDataHandle = { "ReplicatedTargetDataHandle", nullptr, (EPropertyFlags)0x0010000008000082, UECodeGen_Private::EPropertyGenFlags::Struct, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms, ReplicatedTargetDataHandle), Z_Construct_UScriptStruct_FGameplayAbilityTargetDataHandle, METADATA_PARAMS(Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ReplicatedTargetDataHandle_MetaData, UE_ARRAY_COUNT(Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ReplicatedTargetDataHandle_MetaData)) }; // 3993235140  | |
const UECodeGen_Private::FStructPropertyParams Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ApplicationTag = { "ApplicationTag", nullptr, (EPropertyFlags)0x0010000000000080, UECodeGen_Private::EPropertyGenFlags::Struct, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms, ApplicationTag), Z_Construct_UScriptStruct_FGameplayTag, METADATA_PARAMS(nullptr, 0) }; // 1225434376  | |
const UECodeGen_Private::FStructPropertyParams Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_CurrentPredictionKey = { "CurrentPredictionKey", nullptr, (EPropertyFlags)0x0010000000000080, UECodeGen_Private::EPropertyGenFlags::Struct, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms, CurrentPredictionKey), Z_Construct_UScriptStruct_FPredictionKey, METADATA_PARAMS(nullptr, 0) }; // 2453680625  | |
const UECodeGen_Private::FPropertyParamsBase* const Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::PropPointers[] = {  | |
(const UECodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_AbilityHandle,  | |
(const UECodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_AbilityOriginalPredictionKey,  | |
(const UECodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ReplicatedTargetDataHandle,  | |
(const UECodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_ApplicationTag,  | |
(const UECodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::NewProp_CurrentPredictionKey,  | |
};  | |
#if WITH_METADATA | |
const UECodeGen_Private::FMetaDataPairParam Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::Function_MetaDataParams[] = {  | |
{ "Comment", "/** Replicates targeting data to the server */" },  | |
{ "ModuleRelativePath", "Public/AbilitySystemComponent.h" },  | |
{ "ToolTip", "Replicates targeting data to the server" },  | |
};  | |
#endif | |
const UECodeGen_Private::FFunctionParams Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::FuncParams = { (UObject*(*)())Z_Construct_UClass_UAbilitySystemComponent, nullptr, "ServerSetReplicatedTargetData", nullptr, nullptr, sizeof(AbilitySystemComponent_eventServerSetReplicatedTargetData_Parms), Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::PropPointers, UE_ARRAY_COUNT(Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::PropPointers), RF_Public|RF_Transient|RF_MarkAsNative, (EFunctionFlags)0x80220CC0, 0, 0, METADATA_PARAMS(Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::Function_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::Function_MetaDataParams)) };  | |
UFunction* Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData()  | |
{ | |
static UFunction* ReturnFunction = nullptr;  | |
if (!ReturnFunction)  | |
    { | |
UECodeGen_Private::ConstructUFunction(&ReturnFunction, Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData_Statics::FuncParams);  | |
    } | |
return ReturnFunction;  | |
} | |
const FClassFunctionLinkInfo Z_Construct_UClass_UAbilitySystemComponent_Statics::FuncInfo[] = {  | |
{ &Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData, "ServerSetReplicatedTargetData" }, // 2588216155  | |
} | 
生成代码大致可以分为三个部分内容:
- ServerSetReplicatedTargetData 函数的 MetaData,其中包括描述函数参数的 
UECodeGen_Private::FStructPropertyParams以及函数转为 UFunction 的构造函数Z_Construct_UFunction_UAbilitySystemComponent_ServerSetReplicatedTargetData,之后会在Z_Construct_UClass_UAbilitySystemComponent_Statics类中注册这些 UFunction 工厂函数,在 UClass 的创建的时候把这些 UFunction 也一并创建,然后就可以通过反射进行函数查找了。 
struct FStructPropertyParams // : FPropertyParamsBaseWithOffset  | |
{ | |
const char* NameUTF8;  | |
const char* RepNotifyFuncUTF8;  | |
    EPropertyFlags      PropertyFlags; | |
    EPropertyGenFlags   Flags; | |
    EObjectFlags     ObjectFlags; | |
    int32            ArrayDim; | |
    SetterFuncPtr  SetterFunc; | |
    GetterFuncPtr  GetterFunc; | |
    int32            Offset; | |
UScriptStruct* (*ScriptStructFunc)();  | |
#if WITH_METADATA | |
const FMetaDataPairParam* MetaDataArray;  | |
	int32                               NumMetaData; | |
#endif | |
};  | 
- ServerSetReplicatedTargetData 函数本身,这个函数除了打包参数以外什么都不会去做,而是通过 ProcessEvent 统一调用函数执行,函数查询时通过函数名 "ServerSetReplicatedTargetData"。ProcessEvent 不仅仅会调用函数,还会根据函数的类型、进程的 NetMode、角色的权威性、决定在哪里(本地 or 远程服务器)调用。
 

- execServerSetReplicatedTargetData 函数,该函数内会调用两个固定接口 「xxx_Validate 和 xxx_Implementation」。远程调用的时候,会通过 RPC 获取到函数名 "ServerSetReplicatedTargetData",然后通过 
Object->FindFunction(FunctionName)查找到该函数,execServerSetReplicatedTargetData 的注册是在 StaticRegisterNativesUAbilitySystemComponent 是进行的。 

# execServerSetReplicatedTargetData 展开
// 展开前 | |
DEFINE_FUNCTION(UAbilitySystemComponent::execServerSetReplicatedTargetData)  | |
{ | |
P_GET_STRUCT(FGameplayAbilitySpecHandle,Z_Param_AbilityHandle);  | |
P_GET_STRUCT(FPredictionKey,Z_Param_AbilityOriginalPredictionKey);  | |
P_GET_STRUCT(FGameplayAbilityTargetDataHandle,Z_Param_ReplicatedTargetDataHandle);  | |
P_GET_STRUCT(FGameplayTag,Z_Param_ApplicationTag);  | |
P_GET_STRUCT(FPredictionKey,Z_Param_CurrentPredictionKey);  | |
    P_FINISH; | |
    P_NATIVE_BEGIN; | |
if (!P_THIS->ServerSetReplicatedTargetData_Validate(Z_Param_AbilityHandle,Z_Param_AbilityOriginalPredictionKey,Z_Param_ReplicatedTargetDataHandle,Z_Param_ApplicationTag,Z_Param_CurrentPredictionKey))  | |
    { | |
RPC_ValidateFailed(TEXT("ServerSetReplicatedTargetData_Validate"));  | |
return;  | |
    } | |
P_THIS->ServerSetReplicatedTargetData_Implementation(Z_Param_AbilityHandle,Z_Param_AbilityOriginalPredictionKey,Z_Param_ReplicatedTargetDataHandle,Z_Param_ApplicationTag,Z_Param_CurrentPredictionKey);  | |
    P_NATIVE_END; | |
} | |
// 展开后 | |
void UAbilitySystemComponent::execServerSetReplicatedTargetData(UObject* Context,  | |
FFrame& Stack,  | |
void* const Z_Param__Result)  | |
{ | |
    FGameplayAbilitySpecHandle Z_Param_AbilityHandle; | |
Stack.StepCompiledIn<FStructProperty>(&Z_Param_AbilityHandle);;  | |
    FPredictionKey Z_Param_AbilityOriginalPredictionKey; | |
Stack.StepCompiledIn<FStructProperty>(&Z_Param_AbilityOriginalPredictionKey);;  | |
    FGameplayAbilityTargetDataHandle Z_Param_ReplicatedTargetDataHandle; | |
Stack.StepCompiledIn<FStructProperty>(&Z_Param_ReplicatedTargetDataHandle);;  | |
    FGameplayTag Z_Param_ApplicationTag; | |
Stack.StepCompiledIn<FStructProperty>(&Z_Param_ApplicationTag);;  | |
    FPredictionKey Z_Param_CurrentPredictionKey; | |
Stack.StepCompiledIn<FStructProperty>(&Z_Param_CurrentPredictionKey);;  | |
Stack.Code += !!Stack.Code;;  | |
    { | |
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;;  | |
if (!((ThisClass*)(Context))  | |
->ServerSetReplicatedTargetData_Validate(Z_Param_AbilityHandle,  | |
                                                          Z_Param_AbilityOriginalPredictionKey, | |
                                                          Z_Param_ReplicatedTargetDataHandle, | |
                                                          Z_Param_ApplicationTag, | |
Z_Param_CurrentPredictionKey))  | |
        { | |
RPC_ValidateFailed(TEXT("ServerSetReplicatedTargetData_Validate"));  | |
return;  | |
        } | |
((ThisClass*)(Context))  | |
->ServerSetReplicatedTargetData_Implementation(Z_Param_AbilityHandle,  | |
                                                           Z_Param_AbilityOriginalPredictionKey, | |
                                                           Z_Param_ReplicatedTargetDataHandle, | |
                                                           Z_Param_ApplicationTag, | |
Z_Param_CurrentPredictionKey);  | |
    } | |
} | 
展开后的 execServerSetReplicatedTargetData 会执行 ServerSetReplicatedTargetData_Validate 和 ServerSetReplicatedTargetData_Implementation。
# Rpc Bunch 包结构

- FNetworkGUID 标识调用对象
 - FieldNetIndex 标识调用函数
 
# RPC 调用链路图
Client <-> DS

ListenServer && Stalone
