925236118/alphaagent/godot-online-multiplayer
Claude Code and agent skill by 925236118/alphaagent
Trust tier 3
- community
- By 925236118
- Coding
- 925236118/alphaagent
- addons/agent/skills/default_skills/godot-online-multiplayer/SKILL.md
- Updated 2 Oct 2026
- Version 1.0.01 version recorded
Source check pending
Checking that the SKILL.md file is still in the repository.
Godot 4 多人游戏核心模式,包括场景管理、玩家生命周期、死亡复活机制。
Install
npx vskill@latest install 925236118/alphaagent/godot-online-multiplayerSKILL.md
Godot Online Multiplayer
Godot 4 多人游戏核心模式,涵盖场景管理、玩家生命周期、死亡复活等机制。
When to Use This Skill
- 构建多人在线游戏
- 实现玩家生成与销毁
- 处理多人游戏中的死亡与复活
- 管理游戏流程状态机
- 同步玩家数据
Core Concepts
多人游戏架构
MultiplayerHost (服务器/主机)├── MultiplayerSpawner (自动生成节点)├── MultiplayerSynchronizer (状态同步)└── PlayerManager (玩家管理)MultiplayerPeers (客户端/对等端)├── NetworkedMultiplayerENet (网络连接)└── Player instances (同步的玩家)
1. 场景结构
主游戏场景
gdscript
# main.tscn 场景结构# Main (Node)# ├── GameManager (Autoload)# ├── MultiplayerSpawner (自动生成玩家)# ├── World (Node2D)# │ ├── SpawnPoints (Node)# │ └── Enemies (Node)# └── UI (CanvasLayer)
玩家场景
gdscript
# player.tscn 场景结构# Player (CharacterBody2D)# ├── Sprite2D# ├── CollisionShape2D# ├── HealthComponent# ├── HitboxComponent# ├── NameLabel (Label)# └── HealthBar (ProgressBar)
2. MultiplayerSpawner 使用
gdscript
# PlayerSpawner.gdclass_name PlayerSpawnerextends MultiplayerSpawner## 自动生成玩家节点## 当对等端连接时自动生成玩家实例signal player_spawned(player: Node, peer_id: int)signal player_despawned(player: Node, peer_id: int)@export var player_scene: PackedScenefunc _ready() -> void:# 设置生成路径spawn_path = ^"/root/Main/Players"# 连接信号spawned.connect(_on_spawned)despawned.connect(_on_despawned)func _on_spawned(node: Node) -> void:var peer_id := multiplayer.get_remote_sender_id()print("玩家生成: %s (Peer ID: %d)" % [node.name, peer_id])player_spawned.emit(node, peer_id)func _on_despawned(node: Node) -> void:var peer_id := multiplayer.get_remote_sender_id()print("玩家销毁: %s (Peer ID: %d)" % [node.name, peer_id])player_despawned.emit(node, peer_id)
3. 生成函数
gdscript
# spawn_manager.gdclass_name SpawnManagerextends Node## 管理玩家生成逻辑@export var player_scene: PackedScene@export var spawn_points: Array[Marker2D] = []var _spawn_points_container: Node2Dfunc _ready() -> void:_spawn_points_container = $SpawnPointsfunc get_spawn_position(peer_id: int) -> Vector2:"""根据peer_id获取生成位置"""if spawn_points.is_empty():return Vector2.ZERO# 使用 peer_id 哈希选择生成点,实现均衡分布var index := peer_id % spawn_points.size()var spawn_point := spawn_points[index]if spawn_point is Marker2D:return spawn_point.global_positionreturn spawn_point.global_position if spawn_point.has_node(".") else Vector2.ZEROfunc spawn_player(peer_id: int, parent: Node) -> Node:"""生成玩家节点"""var player := player_scene.instantiate()# 设置玩家名称为 peer_idplayer.name = str(peer_id)# 设置初始位置player.global_position = get_spawn_position(peer_id)# 配置玩家if player.has_method("setup"):player.setup(peer_id)parent.add_child(player)# 只在服务器上设置网络主人if multiplayer.is_server():player.set_multiplayer_authority(peer_id)return playerfunc despawn_player(peer_id: int, parent: Node) -> void:"""销毁玩家节点"""var player := parent.get_node_or_null(str(peer_id))if player:player.queue_free()
4. 玩家加入流程
gdscript
# game_manager.gd (Autoload)extends Nodesignal player_joined(peer_id: int)signal player_left(peer_id: int)signal game_startedsignal game_ended(winner_id: int)enum GameState { WAITING, PLAYING, GAME_OVER }var game_state: GameState = GameState.WAITINGvar players: Dictionary = {} # peer_id -> PlayerDatavar _min_players: int = 1var _max_players: int = 4func _ready() -> void:# 设置网络回调multiplayer.peer_connected.connect(_on_peer_connected)multiplayer.peer_disconnected.connect(_on_peer_disconnected)# 如果是服务器,启动游戏循环if multiplayer.is_server():_check_start_game()func _on_peer_connected(peer_id: int) -> void:print("玩家连接: %d" % peer_id)# 创建玩家数据var player_data := PlayerData.new()player_data.peer_id = peer_idplayer_data.name = "Player_%d" % peer_idplayer_data.is_alive = trueplayer_data.score = 0players[peer_id] = player_data# 通知所有客户端有新玩家加入rpc("_sync_player_joined", peer_id, player_data.to_dict())player_joined.emit(peer_id)# 检查是否可以开始游戏_check_start_game()func _on_peer_disconnected(peer_id: int) -> void:print("玩家断开: %d" % peer_id)# 清理玩家数据var player_data := players.get(peer_id)if player_data:player_data.free()players.erase(peer_id)# 通知所有客户端rpc("_sync_player_left", peer_id)player_left.emit(peer_id)# 检查游戏是否结束if game_state == GameState.PLAYING and players.size() < 2:_end_game(0) # 剩余玩家获胜@rpc(call_local = true)func _sync_player_joined(peer_id: int, data: Dictionary) -> void:if not players.has(peer_id):var player_data := PlayerData.new()player_data.from_dict(data)players[peer_id] = player_data@rpc(call_local = true)func _sync_player_left(peer_id: int) -> void:var player_data := players.get(peer_id)if player_data:player_data.free()players.erase(peer_id)func _check_start_game() -> void:if game_state == GameState.WAITING and players.size() >= _min_players:start_game()func start_game() -> void:game_state = GameState.PLAYINGgame_started.emit()# 重置所有玩家状态for peer_id in players.keys():var data := players[peer_id]data.is_alive = truedata.lives = 3data.score = 0rpc("_sync_game_state", GameState.PLAYING)@rpc(call_local = true)func _sync_game_state(state: GameState) -> void:game_state = statefunc _end_game(winner_id: int) -> void:game_state = GameState.GAME_OVERgame_ended.emit(winner_id)rpc("_sync_game_state", GameState.GAME_OVER)rpc("_sync_winner", winner_id)@rpc(call_local = true)func _sync_winner(winner_id: int) -> void:pass # UI显示胜利者# PlayerData.gdclass_name PlayerDataextends RefCountedvar peer_id: intvar name: Stringvar is_alive: boolvar lives: int = 3var score: int = 0func to_dict() -> Dictionary:return {"peer_id": peer_id,"name": name,"is_alive": is_alive,"lives": lives,"score": score}func from_dict(data: Dictionary) -> void:peer_id = data.get("peer_id", 0)name = data.get("name", "")is_alive = data.get("is_alive", true)lives = data.get("lives", 3)score = data.get("score", 0)
5. 断开处理
gdscript
# connection_manager.gdclass_name ConnectionManagerextends Nodesignal connection_failedsignal connection_succeededsignal server_disconnectedconst DEFAULT_PORT := 8765const MAX_PLAYERS := 8func _ready() -> void:# 显示主菜单UIpassfunc create_server(port: int = DEFAULT_PORT) -> bool:"""创建服务器"""var peer := ENetMultiplayerPeer.new()var error := peer.create_server(port, MAX_PLAYERS)if error != OK:push_error("无法创建服务器: %s" % error)return falsemultiplayer.multiplayer_peer = peer# 连接信号peer.peer_connected.connect(_on_peer_connected)peer.peer_disconnected.connect(_on_peer_disconnected)print("服务器创建成功,端口: %d" % port)connection_succeeded.emit()return truefunc join_server(ip: String, port: int = DEFAULT_PORT) -> bool:"""加入服务器"""var peer := ENetMultiplayerPeer.new()var error := peer.create_client(ip, port)if error != OK:push_error("无法连接服务器: %s" % error)connection_failed.emit()return falsemultiplayer.multiplayer_peer = peer# 连接信号peer.connection_succeeded.connect(_on_connection_succeeded)peer.connection_failed.connect(_on_connection_failed)peer.server_disconnected.connect(_on_server_disconnected)print("正在连接 %s:%d..." % [ip, port])return truefunc _on_peer_connected(peer_id: int) -> void:print("对等端连接: %d" % peer_id)func _on_peer_disconnected(peer_id: int) -> void:print("对等端断开: %d" % peer_id)# GameManager 处理玩家离开逻辑func _on_connection_succeeded() -> void:print("连接成功!")connection_succeeded.emit()func _on_connection_failed() -> void:print("连接失败!")connection_failed.emit()func _on_server_disconnected() -> void:print("服务器断开")server_disconnected.emit()# 返回主菜单get_tree().change_scene_to_file("res://scenes/menu.tscn")func disconnect_from_server() -> void:if multiplayer.multiplayer_peer:multiplayer.multiplayer_peer.close()multiplayer.multiplayer_peer = null
6. 死亡与复活
gdscript
# player.gdclass_name Playerextends CharacterBody2Dsignal died(peer_id: int, killer_id: int)signal respawned(peer_id: int)@export var respawn_time: float = 3.0@export var invincibility_after_spawn: float = 2.0var peer_id: int = 0var is_alive: bool = truevar killer_id: int = 0var _respawn_timer: Timervar _invincibility_timer: Timervar _health_component: HealthComponentfunc _ready() -> void:# 获取生命组件_health_component = $HealthComponentif _health_component:_health_component.died.connect(_on_died)# 创建计时器_respawn_timer = Timer.new()_respawn_timer.one_shot = true_respawn_timer.timeout.connect(_on_respawn_timer_timeout)add_child(_respawn_timer)_invincibility_timer = Timer.new()_invincibility_timer.one_shot = true_invincibility_timer.timeout.connect(_on_invincibility_timeout)add_child(_invincibility_timer)func setup(p_id: int) -> void:peer_id = p_idname = str(p_id)# 设置网络权限set_multiplayer_authority(p_id)# 在所有客户端上设置可见性.rpc("_sync_setup", p_id)@rpcfunc _sync_setup(p_id: int) -> void:peer_id = p_idname = str(p_id)func _on_died(source_peer_id: int) -> void:if not is_alive:returnis_alive = falsekiller_id = source_peer_iddied.emit(peer_id, killer_id)# 通知服务器rpc("_notify_death", peer_id, source_peer_id)@rpc(call_local = true)func _notify_death(victim_id: int, killer_id: int) -> void:died.emit(victim_id, killer_id)# 服务器处理死亡逻辑if multiplayer.is_server():GameManager.on_player_died(victim_id, killer_id)# 开始复活计时_start_respawn_timer()func _start_respawn_timer() -> void:_respawn_timer.start(respawn_time)func _on_respawn_timer_timeout() -> void:if is_networked():rpc("_request_respawn", peer_id)else:_do_respawn()@rpcfunc _request_respawn(p_id: int) -> void:if multiplayer.is_server():_do_respawn_for_player(p_id)func _do_respawn_for_player(p_id: int) -> void:# 服务器检查是否可以复活var player_data := GameManager.players.get(p_id)if player_data and player_data.lives > 0:rpc("_perform_respawn", p_id)@rpc(call_local = true)func _perform_respawn(p_id: int) -> void:if peer_id != p_id:return# 重置状态is_alive = true_health_component.current_health = _health_component.max_health# 移动到生成点global_position = SpawnManager.get_spawn_position(p_id)# 无敌时间_invincibility_timer.start(invincibility_after_spawn)respawned.emit(peer_id)func _on_invincibility_timeout() -> void:# 恢复碰撞passfunc take_damage(amount: int, source_peer_id: int) -> void:if not is_alive:returnif _health_component:_health_component.take_damage(amount, get_node_or_null(str(source_peer_id)))
7. 游戏结束检查
gdscript
# game_manager.gd 继续
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingaddons/agent/skills/default_skills/godot-online-multiplayer/SKILL.md
Popularity
- Repository stars
- 103
- Repository forks
- 14
- 7-day trend score
- 23
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/925236118/alphaagent/godot-online-multiplayer)Something wrong with this skill or its page? Tell us.