重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
godot-multiplayer-networking by thedivergentai/gd-agentic-skills
npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-multiplayer-networking权威服务器、客户端预测和状态同步定义了健壮的多人游戏。
用于调整 ENet 通道、压缩和带宽阈值的专家逻辑。
专业的序列化工具,用于将数据按位打包到 PackedByteArray。
用于检测专用服务器模式并解析无头启动 CLI 参数的逻辑。
用于高保真延迟跟踪的 RTT(往返时间)和抖动监控系统。
用于无需主服务器的本地服务器发现的 UDP 广播系统。
动态同步管理器,可根据对等连接质量调整同步速率。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
服务器权威状态验证和强制校正逻辑。
用于优化大规模世界带宽的兴趣管理系统。
用于 RPC 安全的基本洪水保护和反垃圾邮件管理器。
用于将永久 UserID 映射到易失性网络 PeerID 的映射工具。
Reliable — 可靠数据包会阻塞所有后续数据包,直到被确认(队头阻塞)。请使用 UnreliableOrdered。net_lan_discovery.gd)或通过 CLI/UI 传递 IP。net_adaptive_sync_throttle.gd 仅在状态发生显著变化时或按固定频率(例如 20Hz)发送更新。JSON — 字符串序列化在网络传输中开销巨大。使用按位打包(net_packet_bit_packer.gd)将数据包保持在 100 字节以下。net_visibility_grid_culling.gd)。森林中的玩家不需要城市中玩家的位置。net_packet_rate_limiter.gd。UserID(net_custom_id_mapper.gd)。--headless(net_headless_server_auto_start.gd)以节省资源并确保稳定性。权威服务器模型:
点对点:
extends Node
var peer := ENetMultiplayerPeer.new()
func host_game(port: int = 7777) -> void:
peer.create_server(port, 4) # 最多 4 名玩家
multiplayer.multiplayer_peer = peer
print("服务器已启动,端口 ", port)
func join_game(ip: String, port: int = 7777) -> void:
peer.create_client(ip, port)
multiplayer.multiplayer_peer = peer
print("正在连接到 ", ip)
func _ready() -> void:
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
multiplayer.connected_to_server.connect(_on_connected)
multiplayer.connection_failed.connect(_on_connection_failed)
func _on_peer_connected(id: int) -> void:
print("玩家已连接: ", id)
func _on_peer_disconnected(id: int) -> void:
print("玩家已断开连接: ", id)
func _on_connected() -> void:
print("已连接到服务器!")
func _on_connection_failed() -> void:
print("连接失败")
extends CharacterBody2D
# 在所有对等体上调用
@rpc("any_peer", "call_local")
func take_damage(amount: int) -> void:
health -= amount
if health <= 0:
die()
# 用法:在特定对等体上调用
take_damage.rpc_id(1, 50) # 在服务器上调用(ID 1)
take_damage.rpc(50) # 在所有对等体上调用
# 只有服务器可以调用,在所有客户端上运行
@rpc("authority", "call_remote")
func server_spawn_enemy(pos: Vector2) -> void:
pass
# 任何对等体都可以调用,也在本地运行
@rpc("any_peer", "call_local")
func player_chat(message: String) -> void:
pass
# 可靠(类似 TCP)与不可靠(类似 UDP)
@rpc("any_peer", "call_local", "reliable")
func important_event() -> void:
pass
@rpc("any_peer", "call_local", "unreliable")
func position_update(pos: Vector2) -> void:
pass
# 添加 MultiplayerSpawner 节点
# 设置生成路径和场景
extends Node
@onready var spawner := $MultiplayerSpawner
func _ready() -> void:
spawner.spawn_function = spawn_player
func spawn_player(data: Variant) -> Node:
var player := preload("res://player.tscn").instantiate()
player.name = str(data) # 使用对等体 ID 作为名称
return player
# 添加到同步节点
# 设置要同步的属性
# 场景结构:
# Player (CharacterBody2D)
# ├─ MultiplayerSynchronizer
# │ └─ 复制配置:
# │ - position (sync)
# │ - velocity (sync)
# │ - health (sync)
# └─ Sprite2D
# lobby_manager.gd (AutoLoad)
extends Node
signal player_joined(id: int, info: Dictionary)
signal player_left(id: int)
var players: Dictionary = {}
func _ready() -> void:
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
func _on_peer_connected(id: int) -> void:
# 请求玩家信息
request_player_info.rpc_id(id)
func _on_peer_disconnected(id: int) -> void:
players.erase(id)
player_left.emit(id)
@rpc("any_peer", "reliable")
func request_player_info() -> void:
var sender_id := multiplayer.get_remote_sender_id()
receive_player_info.rpc_id(sender_id, {
"name": PlayerSettings.player_name,
"color": PlayerSettings.player_color
})
@rpc("any_peer", "reliable")
func receive_player_info(info: Dictionary) -> void:
var sender_id := multiplayer.get_remote_sender_id()
players[sender_id] = info
player_joined.emit(sender_id, info)
extends CharacterBody2D
var puppet_position: Vector2
var puppet_velocity: Vector2
func _physics_process(delta: float) -> void:
if is_multiplayer_authority():
# 本地玩家:处理输入
_handle_input(delta)
move_and_slide()
# 向其他人发送位置
sync_position.rpc(global_position, velocity)
else:
# 远程玩家:插值
global_position = global_position.lerp(puppet_position, 10.0 * delta)
@rpc("any_peer", "unreliable")
func sync_position(pos: Vector2, vel: Vector2) -> void:
puppet_position = pos
puppet_velocity = vel
# 检查谁拥有此节点
func _ready() -> void:
# 将权限设置为所有者对等体
set_multiplayer_authority(peer_id)
func _process(delta: float) -> void:
if not is_multiplayer_authority():
return # 如果不是所有者则跳过
# 只有权限所有者处理此逻辑
@rpc("any_peer", "call_local")
func player_action(action: String) -> void:
if not multiplayer.is_server():
return # 只有服务器验证
var sender := multiplayer.get_remote_sender_id()
if not _is_valid_action(sender, action):
return
_apply_action.rpc(sender, action)
# 位置:不可靠(频繁)
@rpc("any_peer", "unreliable")
func sync_position(pos: Vector2) -> void:
pass
# 伤害:可靠(重要)
@rpc("authority", "reliable")
func apply_damage(amount: int) -> void:
pass
var target_position: Vector2
func _process(delta: float) -> void:
if not is_multiplayer_authority():
position = position.lerp(target_position, 15.0 * delta)
每周安装次数
62
代码仓库
GitHub 星标数
59
首次出现
2026年2月10日
安全审计
安装于
opencode62
codex61
gemini-cli61
kimi-cli60
github-copilot60
amp60
Authoritative servers, client prediction, and state synchronization define robust multiplayer.
Expert logic for tuning ENet channels, compression, and bandwidth thresholds.
Professional manual serialization tools for bit-packing data into PackedByteArray.
Logic for detecting dedicated server mode and parsing CLI arguments for headless launch.
RTT (Round Trip Time) and Jitter monitoring system for high-fidelity lag tracking.
UDP broadcasting system for local server discovery without master servers.
Dynamic synchronization manager that adapts sync-rates to peer connection quality.
Server-authoritative state validation and forced-correction logic.
Interest Management system for optimizing bandwidth in large-scale worlds.
Essential flood-protection and anti-spam manager for RPC security.
Mapping utility for linking permanent UserIDs to volatile Network PeerIDs.
Reliable for high-frequency data (Position/Movement) — Reliable packets block all following packets until acknowledged (Head-of-Line blocking). Use UnreliableOrdered.net_lan_discovery.gd) or pass the IP via CLI/UI.net_adaptive_sync_throttle.gd to only send updates when state changes significantly or at fixed Hz intervals (e.g., 20Hz).JSON for high-speed synchronization — String serialization is massive over the wire. Use bit-packing (net_packet_bit_packer.gd) to keep packets under 100 bytes.net_visibility_grid_culling.gd). A player in the forest doesn't need the position of a player in the city.net_packet_rate_limiter.gd.UserIDs (net_custom_id_mapper.gd) from a database.--headless (net_headless_server_auto_start.gd) to save resources and ensure stability.Authoritative Server Model:
Peer-to-Peer:
extends Node
var peer := ENetMultiplayerPeer.new()
func host_game(port: int = 7777) -> void:
peer.create_server(port, 4) # Max 4 players
multiplayer.multiplayer_peer = peer
print("Server started on port ", port)
func join_game(ip: String, port: int = 7777) -> void:
peer.create_client(ip, port)
multiplayer.multiplayer_peer = peer
print("Connecting to ", ip)
func _ready() -> void:
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
multiplayer.connected_to_server.connect(_on_connected)
multiplayer.connection_failed.connect(_on_connection_failed)
func _on_peer_connected(id: int) -> void:
print("Player connected: ", id)
func _on_peer_disconnected(id: int) -> void:
print("Player disconnected: ", id)
func _on_connected() -> void:
print("Connected to server!")
func _on_connection_failed() -> void:
print("Connection failed")
extends CharacterBody2D
# Called on all peers
@rpc("any_peer", "call_local")
func take_damage(amount: int) -> void:
health -= amount
if health <= 0:
die()
# Usage: Call on specific peer
take_damage.rpc_id(1, 50) # Call on server (ID 1)
take_damage.rpc(50) # Call on all peers
# Only server can call, runs on all clients
@rpc("authority", "call_remote")
func server_spawn_enemy(pos: Vector2) -> void:
pass
# Any peer can call, runs locally too
@rpc("any_peer", "call_local")
func player_chat(message: String) -> void:
pass
# Reliable (TCP-like) vs Unreliable (UDP-like)
@rpc("any_peer", "call_local", "reliable")
func important_event() -> void:
pass
@rpc("any_peer", "call_local", "unreliable")
func position_update(pos: Vector2) -> void:
pass
# Add MultiplayerSpawner node
# Set spawn path and scenes
extends Node
@onready var spawner := $MultiplayerSpawner
func _ready() -> void:
spawner.spawn_function = spawn_player
func spawn_player(data: Variant) -> Node:
var player := preload("res://player.tscn").instantiate()
player.name = str(data) # Use peer ID as name
return player
# Add to synchronized node
# Set properties to sync
# Scene structure:
# Player (CharacterBody2D)
# ├─ MultiplayerSynchronizer
# │ └─ Replication config:
# │ - position (sync)
# │ - velocity (sync)
# │ - health (sync)
# └─ Sprite2D
# lobby_manager.gd (AutoLoad)
extends Node
signal player_joined(id: int, info: Dictionary)
signal player_left(id: int)
var players: Dictionary = {}
func _ready() -> void:
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
func _on_peer_connected(id: int) -> void:
# Request player info
request_player_info.rpc_id(id)
func _on_peer_disconnected(id: int) -> void:
players.erase(id)
player_left.emit(id)
@rpc("any_peer", "reliable")
func request_player_info() -> void:
var sender_id := multiplayer.get_remote_sender_id()
receive_player_info.rpc_id(sender_id, {
"name": PlayerSettings.player_name,
"color": PlayerSettings.player_color
})
@rpc("any_peer", "reliable")
func receive_player_info(info: Dictionary) -> void:
var sender_id := multiplayer.get_remote_sender_id()
players[sender_id] = info
player_joined.emit(sender_id, info)
extends CharacterBody2D
var puppet_position: Vector2
var puppet_velocity: Vector2
func _physics_process(delta: float) -> void:
if is_multiplayer_authority():
# Local player: process input
_handle_input(delta)
move_and_slide()
# Send position to others
sync_position.rpc(global_position, velocity)
else:
# Remote player: interpolate
global_position = global_position.lerp(puppet_position, 10.0 * delta)
@rpc("any_peer", "unreliable")
func sync_position(pos: Vector2, vel: Vector2) -> void:
puppet_position = pos
puppet_velocity = vel
# Check who owns this node
func _ready() -> void:
# Set authority to owner peer
set_multiplayer_authority(peer_id)
func _process(delta: float) -> void:
if not is_multiplayer_authority():
return # Skip if not owner
# Only authority processes this
@rpc("any_peer", "call_local")
func player_action(action: String) -> void:
if not multiplayer.is_server():
return # Only server validates
var sender := multiplayer.get_remote_sender_id()
if not _is_valid_action(sender, action):
return
_apply_action.rpc(sender, action)
# Position: unreliable (frequent)
@rpc("any_peer", "unreliable")
func sync_position(pos: Vector2) -> void:
pass
# Damage: reliable (important)
@rpc("authority", "reliable")
func apply_damage(amount: int) -> void:
pass
var target_position: Vector2
func _process(delta: float) -> void:
if not is_multiplayer_authority():
position = position.lerp(target_position, 15.0 * delta)
Weekly Installs
62
Repository
GitHub Stars
59
First Seen
Feb 10, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode62
codex61
gemini-cli61
kimi-cli60
github-copilot60
amp60
TanStack Query v5 完全指南:React 数据管理、乐观更新、离线支持
2,500 周安装