欢迎光临散文网 会员登陆 & 注册

Godot Multiplayer RPC 实例演示

2023-02-06 19:19 作者:紧果呗  | 我要投稿

### 🟠🟢🔵 Multiplayer RPC 实例演示

  • [Multiplayer Bomber Demo](https://godotengine.org/asset-library/asset/139)

  • [Pong Multiplayer](https://godotengine.org/asset-library/asset/138)

  • [Pong Non-Multiplayer](https://github.com/godotengine/godot-demo-projects/tree/master/2d/pong)

  • [Godot Multiplayer Networking Cheatsheet](https://blog.iancolwell.ca/godot-multiplayer-networking-cheatsheet)

  • [Godot Multiplayer RPC](https://github.com/jeangowhy/godot-tour/tree/4.x/multiplayer_rpc)

使用 Godot 4.x RPC API 进行网络游戏开发的工作流程概要:

  •  配置 MultiplayerPeer 启动相应的服务器/客户端;

  •  建立连接,记录 peer ID 并给相应的节点设置主控端 ID;

  •  配置 RPC API,根据需要设置 RPC 的调用方式,主要是:any_peer authority call_local call_remote

  •  通过 is_network_master() is_multiplayer_authority() 主动判断当前节点是否归属于主控;

  •  执行 rpc()rpc_id() 等方法执行 RPC 调用远程方法,进行数据同步;

  •  处理网络连接,以下结束连接;

使用 RPC API 涉及到的数据同步,需要通过定义各种 RPC 方法来实现,比如,以下例子中用于记录所有客户连接标志的 connected_peer_ids,在服务器端总能记录到所有客户端的 ID。但是新加入的客户端,只知道自己与服务器的连接,其它客户端的连接需要通过查询(同步)服务器中的数据。所以,每当有新客户端发出连接请求时,服务端都需要执行一个 new_peer_broadcast 广播,远程调用所有客户端的方法,以创建相应的新玩家节点。同时,对于原有玩家,需要通过 rpc_id() 指定 ID 调用新玩家主机上的 API,同步创建与服务场景树一致的节点结构:

注意,默认的 @rpc 标注是 call_remote 方式调用,不会在主控端运行,只在其它所有远程端执行数据同步。

因为连接信号是服务器端的行为,所以 @rpc 方式调用就是在所有客户端执行,由服务器发起 RPC 调用,但是不包括服务器。


使用 RPC API 最后阶段包含结束连接处理,当客户端或服务器端断开连接,就应该做相当的处理。客户端结束,整个连网系统还在运行,只是其中一个对等端的退出,需要将其占用的资源清理掉。而对于服务器结束,所以客户端都会失去连网功能,要么等待服务器重新启动再尝试连接,要么清理所有客户端相关资源。MultiplayerPeer 需要关闭,并且释放 multiplayer_peer = null,同时场景中也不能再调用相关的 RPC API。

通过 MultiplayerAPI.has_multiplayer_peer() 可以查询当前的连接状态,作为执行 RPC 的依据。

服务器端开启后就会进行侦听,等待客户端的连接请求。而客户端连接服务器则需要根据网络状态而定,有时可能因为网络不稳定,需要越长时间的才能建立连接。更坏的情况是,根本不能正常建立连接,经过一段时间尝试还不能建立连接,就会因为连接超时,进而触发 connetion_failed 信号。可以说,connected_to_server 是最不重要的连接信号之一。

服务器信号使用不恰当可能会导致服务器端在首个客户端连接时,重复出现 ID = 1 的 peer 连接。一般只需要将客户端的信号,与服务器端的信号分开连接使用。

Godot 3 关键字与 Godot 4 标注的等价关系参考:

这个表可以作为 Godot 3.5 与 Godot 4.x Multiplayer RPC 开发参考。


标注使用示范如下,假设通过一个 Area3D 的输入事件触发 RPC 调用:

  •  shake_me() 方法使用默认标注,即在主控执行远端同步,等同旧版本的 `master` 关键字;

  •  shake_all() 方法所有对等端都执行,并且执行远端同步,等同旧版本的 `remote` 关键字;

  •  clicked_all() 方法在所有对等端执行,并且执行本地与远端同步,等同旧版本的 `remotesync` 关键字。

总结来看,network master 也好,multiplayer authority 也好,就是一个主控概念。场景树中所有节点都可以归属给网络中的一个对等端,而默认归属为服务器端。比如,创建一个节点 Player,默认状态就归属于服务器,在所有联网主机中它应该都有一个同样的副本,那么:这个节点定义的 "authority" 方法,在服务器执行时,通过查询当下 MultiplayerPeer 所关联的 ID,即可以知道当下的 peer ID 与 Player 归属一致,所以方法可以执行。在其它客户端,同一 Player 方法就会因为主机所分配的 peer ID 值与 Player 节点归属不一致,而不会被执行。


而对于标注为 "any_peer" 的方法,相当于广播方法,假设在某一个客户中执行,会向所有主机通报:现在要执行这个 "any_peer" 标注过的方法。如果还配合 "call_local",那么主动发起调用的这个客户机上也会执行这个方法,而不是单纯向其它主机发出 RPC 调用。


具体参数使用可以参考源代码 GDScriptParser::rpc_annotation() 方法中的定义:

示范工程只包含两个场景:

  • player.tscn 玩家场景节点,提供玩家的基本角色行为和外观;

  • main.tscn 主场景,提供连接类型选择界面;

主场景使用的 main_rpc.gd 脚本参考如下:

玩家场景使用的脚本参考:


Godot Multiplayer RPC 实例演示的评论 (共 条)

分享到微博请遵守国家法律