返回技能市场
开发运维 安全

godot-multiplayer

@admin/godot-multiplayer

构建 Godot 高级多人网络,配置 ENet 客户端与服务器、RPC、节点权限及玩家和世界状态同步。

admin 热度 230v0.0.1

Godot 多人游戏 (4.x 高级)

连接对等节点,使用 @rpc 远程调用函数,分配权限,并使用 MultiplayerSpawner/MultiplayerSynchronizer 复制状态。 目标版本为 Godot 4.7 (ENet)。将所有客户端输入视为不受信任;保持服务器权威。

何时使用

  • 添加网络多人游戏时使用:通过 ENet 托管/加入、调用 RPC、
  • 分配每个节点的权限,或在各个对等节点之间自动生成/同步节点。

**何时*不*使用:** 本地分屏(无网络);原始 TCP/UDP/WebSocket 协议 工作(低层 PacketPeer);HTTP 请求。对于保存/持久化 → save-systems

核心工作流

  1. 创建对等节点 (ENetMultiplayerPeer),调用 create_server(port, max)
  2. create_client(ip, port),并将其分配给 multiplayer.multiplayer_peer。 服务器的唯一 ID 始终为 1;客户端获得随机正数 ID。

  3. 处理连接信号multiplayer 上:peer_connected(id)
  4. peer_disconnected(id)connected_to_serverconnection_failedserver_disconnected

  5. 定义 RPC 使用 @rpc(...)。通过 rpc()(所有对等节点)或
  6. rpc_id(peer_id)(单个对等节点)在 Callable 上调用它们。在其中,multiplayer.get_remote_sender_id() 会告诉你是谁发送的。

  7. 保持 RPC 签名在每个运行该脚本的对等节点上完全一致 — Godot 会对脚本中所有
  8. @rpc 方法进行校验和检查;不匹配会导致静默失败。

  9. 分配权限 每个节点使用 set_multiplayer_authority(id);通过
  10. is_multiplayer_authority() 限制输入/RPC。

  11. 复制状态 使用 MultiplayerSpawner(在客户端自动实例化场景)和
  12. MultiplayerSynchronizer(自动同步选定的属性)。

  13. 在服务器上进行验证。 不要信任客户端报告的位置/结果。

模式

1. 托管或加入 (ENet)

const PORT := 7000
const MAX_PLAYERS := 8

func host() -> void:
    var peer := ENetMultiplayerPeer.new()
    var err := peer.create_server(PORT, MAX_PLAYERS)
    if err != OK:
        push_error("Cannot host: %s" % err); return
    multiplayer.multiplayer_peer = peer
    multiplayer.peer_connected.connect(_on_peer_connected)

func join(ip := "127.0.0.1") -> void:
    var peer := ENetMultiplayerPeer.new()
    peer.create_client(ip, PORT)
    multiplayer.multiplayer_peer = peer
    multiplayer.connected_to_server.connect(func(): print("connected"))

func leave() -> void:
    multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()

2. RPC:客户端向服务器发送输入 (any_peer, call_local)

func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("fire") and is_multiplayer_authority():
        request_fire.rpc_id(1)          # 仅发送给服务器 (id 1)

# 客户端可以调用此函数;它在服务器上运行(如果服务器也是玩家,则在本地运行)。
@rpc("any_peer", "call_local", "reliable")
func request_fire() -> void:
    var sender := multiplayer.get_remote_sender_id()
    if not _can_fire(sender):           # 服务器端验证
        return
    spawn_projectile.rpc(sender)        # 告诉每个人生成它

@rpc("authority", "call_local", "reliable")
func spawn_projectile(owner_id: int) -> void:
    _do_spawn(owner_id)

3. 每个节点权限(每个玩家控制自己的头像)

extends CharacterBody2D

func _ready() -> void:
    # 节点名称是拥有该节点的 peer 的 id;该 peer 是权限拥有者。
    set_multiplayer_authority(name.to_int())

func _physics_process(delta: float) -> void:
    if not is_multiplayer_authority():
        return                          # 只有拥有者读取输入并移动
    velocity = Input.get_vector("left", "right", "up", "down") * 200.0
    move_and_slide()

4. MultiplayerSynchronizer 配置(编辑器 + 复制)

# 添加一个 MultiplayerSynchronizer 子节点;在其 Replication 编辑器中添加要
# 同步的属性(例如 position, velocity)。为每个属性设置 "Sync"/"Spawn" 标志。从代码中,你
# 可以限定可见性:
@onready var sync: MultiplayerSynchronizer = $MultiplayerSynchronizer

func _ready() -> void:
    # 仅将此节点复制给特定的对等节点(例如私有信息)。
    sync.set_visibility_for(target_peer_id, true)

陷阱

  • RPC 签名校验和。 脚本中的每个 @rpc 方法必须在客户端和服务器构建中
  • 以相同的声明存在 — *即使是未使用的方法*。不匹配会导致指向错误函数的 错误。参数名称/数量不会被检查,但 RPC 集合及其注解会被检查。

  • 默认 @rpc"authority" 除非你设置 "any_peer",否则调用它的客户端会被忽略。使用 "call_local" 以便主机(也是玩家)也能运行它。
  • NodePaths 必须在各个对等节点之间匹配。 RPC 路由使用节点的路径/名称;在所有对等节点上以相同的名称生成节点(使用 MultiplayerSpawneradd_child(node, true) 以获得可读、确定性的名称)。
  • 信任客户端。 永远不要让客户端直接设置权威状态(生命值、位置、命中)。发送*意图*,在服务器上进行验证,然后广播结果。
  • 在非 Node 类上的 RPC 会失败。 @rpc 方法必须在 Node 派生类上,而不是普通的 Resource/RefCounted 上。
  • RPC 不序列化 Objects/Callables。 传递普通数据(整数、字符串、数组、字典、PackedArrays)。
  • 忘记重置对等节点。 要干净地断开连接,设置
  • multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()

  • Android 需要在导出预设中拥有 INTERNET 权限,否则所有网络通信都会被阻止。

参考

  • 有关 MultiplayerSpawner 设置、传输模式/通道、SceneMultiplayer
  • 认证(auth_callback/complete_auth)、大厅框架以及专用服务器 导出说明,请阅读 references/replication-and-rpc.md

相关技能

  • godot-nodes-scenes — 实例化将被生成/同步的场景。
  • godot-signals-groups — 连接信号和事件流。
  • godot-export — 导出无头专用服务器构建。
qianwen skills install @admin/godot-multiplayer