6. RPC
6.1. RPC是网络同步的一部分,全称Remote Procedure Call。属性同步只能从服务端向客户端单向传递信息,而RPC可以双向传递消息
6.2. 类型
6.2.1. Server调用,Actor所属的Client执行
6.2.2. Client调用,Server执行
6.2.3. Server调用,Server和所有Client执行
6.2.4. 定义示例
UFUNCTION(Client)
void ClientRPCFunction();
UFUNCTION(Server)
void ServerRPCFunction();
UFUNCTION(NetMulticast)
void MulticastRPCFunction();
6.3. 调用堆栈
UObject::ProcessEvent
AActor::GetFunctionCallspace
检查函数调用域是否为remote,有趣的是,它返回值按值取与来进行判断,这是因为该函数内部返回的情形并不是单纯的某枚举值,存在返回枚举值A | 枚举值B的状况。
我个人认为既然允许位运算参与逻辑判断,枚举的定义应该是形如0b的,但是UE却是0x定义的,对此表示疑惑
这个枚举定义形式是相当典型的,命名空间内定义Type的实际枚举,配合一个内联函数返回宽字符头来方便转化枚举值为字符串。这显然是调试考量
AActor::CallRemoteFunction
UNetDriver::ProcessRemoteFunction
// 寻找连接,如果需要,则遍历连接
// 如果是多播
InternalProcessRemoteFunctionPrivate
// 如果不是多播
InternalProcessRemoteFunction 调用 InternalProcessRemoteFunctionPrivate
我们可以观察到,如果不是多播,进行rpc的条件是该actor得有连接NetConnection 这就是我们配置actor需要考察owner的原因之一
没有owner,或者说owner链条不到PlayerController,就找不到connection,这一步是过不了的
进一步的,我们可以观察到这俩函数的区别:形参接受的参数connection不同,这个自然,多播需要分别遍历connection,
还有就是parameter的处理区别,在多播的时候会构造一个共享的序列化,其内部是由 FLayout成员中bool变量维护的 只执行一次的函数体
InternalProcessRemoteFunctionPrivate
检查channel是否创建,没创建就创建一个
(居然还有第一人称actor的注释,哈哈哈哈哈)
ProcessRemoteFunctionForChannelPrivate
SendPropertiesForRPC
底层send