Skip to content
Development
Skill

/godot-online-multiplayer

Godot 4 多人游戏核心模式,包括场景管理、玩家生命周期、死亡复活机制。

BOOST
From plugin
alphaagent
10419 skills
Install
$ npx -y skills add 925236118/AlphaAgent --skill godot-online-multiplayer --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/godot-online-multiplayer

Context preview

The summary Claude sees to decide when to auto-load this skill.

Godot 4 多人游戏核心模式,包括场景管理、玩家生命周期、死亡复活机制。

SKILL.md

godot-online-multiplayer.SKILL.md
name: godot-online-multiplayer
description: Godot 4 多人游戏核心模式,包括场景管理、玩家生命周期、死亡复活机制。

Godot Online Multiplayer

Godot 4 多人游戏核心模式,涵盖场景管理、玩家生命周期、死亡复活等机制。

When to Use This Skill

  • 构建多人在线游戏
  • 实现玩家生成与销毁
  • 处理多人游戏中的死亡与复活
  • 管理游戏流程状态机
  • 同步玩家数据

Core Concepts

多人游戏架构

MultiplayerHost (服务器/主机)
├── MultiplayerSpawner (自动生成节点)
├── MultiplayerSynchronizer (状态同步)
└── PlayerManager (玩家管理)

MultiplayerPeers (客户端/对等端)
├── NetworkedMultiplayerENet (网络连接)
└── Player instances (同步的玩家)

1. 场景结构

主游戏场景

# main.tscn 场景结构
# Main (Node)
# ├── GameManager (Autoload)
# ├── MultiplayerSpawner (自动生成玩家)
# ├── World (Node2D)
# │   ├── SpawnPoints (Node)
# │   └── Enemies (Node)
# └── UI (CanvasLayer)

玩家场景

# player.tscn 场景结构
# Player (CharacterBody2D)
# ├── Sprite2D
# ├── CollisionShape2D
# ├── HealthComponent
# ├── HitboxComponent
# ├── NameLabel (Label)
# └── HealthBar (ProgressBar)

2. MultiplayerSpawner 使用

# PlayerSpawner.gd
class_name PlayerSpawner
extends MultiplayerSpawner

## 自动生成玩家节点
## 当对等端连接时自动生成玩家实例

signal player_spawned(player: Node, peer_id: int)
signal player_despawned(player: Node, peer_id: int)

@export var player_scene: PackedScene

func _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. 生成函数

# spawn_manager.gd
class_name SpawnManager
extends Node

## 管理玩家生成逻辑

@export var player_scene: PackedScene
@export var spawn_points: Array[Marker2D] = []

var _spawn_points_container: Node2D

func _ready() -> void:
    _spawn_points_container = $SpawnPoints

func 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_position
    
    return spawn_point.global_position if spawn_point.has_node(".") else Vector2.ZERO

func spawn_player(peer_id: int, parent: Node) -> Node:
    """生成玩家节点"""
    var player := player_scene.instantiate()
    
    # 设置玩家名称为 peer_id
    player.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 player

func despawn_player(peer_id: int, parent: Node) -> void:
    """销毁玩家节点"""
    var player := parent.get_node_or_null(str(peer_id))
    if player:
        player.queue_free()

4. 玩家加入流程

# game_manager.gd (Autoload)
extends Node

signal player_joined(peer_id: int)
signal player_left(peer_id: int)
signal game_started
signal game_ended(winner_id: int)

enum GameState { WAITING, PLAYING, GAME_OVER }

var game_state: GameState = GameState.WAITING
var players: Dictionary = {}  # peer_id -> PlayerData
var _min_players: int = 1
var _max_players: int = 4

func _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_id
    player_data.name = "Player_%d" % peer_id
    player_data.is_alive = true
    player_data.score = 0
    
    players[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.PLAYING
    game_started.emit()
    
    # 重置所有玩家状态
    for peer_id in players.keys():
        var data := players[peer_id]
        data.is_alive = true
        data.lives = 3
        data.score = 0
    
    rpc("_sync_game_state", GameState.PLAYING)

@rpc(call_local = true)
func _sync_game_state(state: GameState) -> void:
    game_state = state

func _end_game(winner_id: int) -> void:
    game_state = GameState.GAME_OVER
    game_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.gd
class_name
Read more
Ships withalphaagent

为Godot引擎编辑器开发的Ai Agent插件

Get the whole plugin

Other skills on alphaagent.

godot-tscn-format
Skill

godot-tscn-format

Godot 4.x .tscn 场景文件纯文本格式规范与 AI 操作指南 — 文件结构、资源引用、 Transform 变换、属性值格式、信号连接,以及 AI 直接读写 .tscn 文件的操作方法。