# 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