版主
☯ 博 丽 不 是 灵 梦 ☯
- 经验
- 7151
- 硬币
- 1212 枚
|
楼主 |
发表于 2024-5-24 11:27:27
|
显示全部楼层
本帖最后由 囿里有条小咸鱼 于 2024-6-26 17:18 编辑
四、对等体
godot中涉及到了一个对等体(peer)的概念。在godot中,在多个端上具有相同名称、且在节点树中层级相同的节点就互为对等体。假设我们有一个服务端A和一个客户端B,A中有三个节点,a,b,c,其中b是a的子节点,c是b的子节点;在客户端B中也有三个节点:a,b,d,其中b,d均为a的子节点。此时我们会发现:在A和B这两个端中,只有a和b是名称相同且节点树层级相同的节点,这时我们就称a和b在A和B这两个端上互为对等体。在Godot中,只有互为对等体的节点才能进行远程通信操作。
五、机端UID
除此之外,在进行联机时,我们还需要知道每个端联机时的身份编号,就好比你邀请别人来你家做客时可能会标记一个客人的编号一样,这个编号就叫做机端UID,可以通过两种方式获取:
- 通过节点或节点树的multiplayer.get_unique_id()方法(如果是客户端,则需要创建好客户端之后才能调用)
- 通过一些信号连接的回调函数所提供的id参数(如multiplayer.peer_connected(id: int)这个信号)
在Godot中,服务端或未联机端的机端UID永远为1,客户端的机端UID则为一个随机值。这个UID非常重要,涉及到后面的远程调用等操作。
六、远程操作以及RPC
联机并不是说一个端上进行了某个操作,另一个端就可以立即同步该操作的,它是一个人为的过程。换言之,需要通过远程操作的手段对对方端的内容进行相应的处理,才能实现双端内容的同步,从而达到联机同步游戏的效果。这里就涉及到一个问题:如何在一个端中调用另一个端内程序的内容呢?对于函数/方法,godot提供了一套机制:rpc
RPC,全称Remote Procedure Call,即远程过程调用,在Godot中,RPC采用的是UDP通信协议(感兴趣的可以百度自行学习相关内容)。通过RPC机制,一个端就可以调用另一个端上的内容了。
对于调用远程函数,可以给一个函数套上@rpc注解,这样这个函数就变成了可被远程调用的函数,即其他端都有可能调用的函数。
- @rpc
- func my_func():
- ...
- # 此时该函数就向其他端开放了
复制代码 需要注意:必须是在不同端中的同名函数/方法才能被远程调用。
要想远程调用其他方法,需要先引用该方法的方法名,然后加上.rpc()才能实现远程调用
rpc()方法也支持传入参数,传入的参数视被rpc的函数情况而定
- # 声明远程方法
- @rpc
- func param(p1, p2):
- ...
- # 调用远程方法
- param.rpc(3, 5) # 参数视被rpc函数的情况而定
复制代码 需要注意的是:在Godot中,由于每个程序中的对象uid彼此独立且随机,而对象在内存中地址也会因各种原因而千变万化,并且rpc调用时只会发送本机数据,不会变通,因此,即便一个方法声明了@rpc,且明面上允许传入对象引用,实际上也无法在该方法声明中传入对象引用,包括节点引用和资源引用,否则在进行rpc时会触发“找不到对象”的报错。对于节点,如果确实需要在远程端进行引用的,可以传递该节点的节点路径,然后在远端通过get_node()进行获取即可。
@rpc还支持传入参数,下列是其参数列表:
- @rpc(param1, param2, param3, channel)
复制代码 其中param1,param2,param3的内容分别为:
param1:
- authority:表示该函数只能由主控端(一般就是服务端)调用,其他端进行rpc时会直接忽略调用该端上的该函数
- any_peer:表示不管是服务端还是客户端,都可以调用该端上的该函数
param2:
- call_remote:表示在进行rpc时,并不会在该端上调用该函数
- call_local:表示在进行rpc时,本地端和远程端都会调用该同名函数
param3:
- reliable:表示在进行rpc时采用完全信任模式,这种模式会在远程游戏丢包时尝试重发,会导致游戏掉帧。一般建议在发送重要数据时选上
- unreliable_ordered:表示在进行rpc时采用有序不信任模式,这种模式会将包进行有序处理,然后逐一发送给远端,并丢弃发送严重延迟的包,导致游戏掉帧的频率适中,一般建议在发送次重要数据时调用
- unreliable:表示在进行rpc时采用不信任模式,这种模式不会处理丢包,但几乎不会导致游戏掉帧,但信息丢失严重。一般建议在发送一般数据时使用。
channel:发送频道,以便在传输数据时不发生包冲突,如果为0则表示采用param3中那三个模式所分别构成的三个频道
其中,param1~3在@rpc中的顺序可以任意,唯独channel只能放在最后。且param1~3中只能选一种参数填入,不允许出现如@rpc("authority", "any_peer")这种情况。@rpc的参数允许开发者能更好的处理@rpc的调用权限、范围和模式。
当然,有些情况下我们只希望命令特定的一个端调用rpc方法,这个时候我们就可以引用函数名然后调用rpc_id()方法来实现。rpc_id()需要传入的参数如下:
- rpc_id(uid: int, ...params)
复制代码 其中uid就是之前提到过的机端UID,params同rpc()内的参数
这样,我们就可以对具有该uid的端进行远程调用
- my_func.rpc_id(1, 3, 5) # uid为1,此时就表示在服务端上调用该函数
- my_func.rpc_id(456098734, 3, 5) # 表示在uid为456098734的端上调用该函数
复制代码 rpc_id功能非常适合做针对某端的操作,如拒绝某端加入游戏,或者将某端踢出等操作。
|
|