Skip to content
Development
Skill

/godot-autoload-patterns

Godot 4 Autoload单例模式最佳实践,包含全局管理、事件总线、信号通信。

BOOST
From plugin
alphaagent
10419 skills
Install
$ npx -y skills add 925236118/AlphaAgent --skill godot-autoload-patterns --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-autoload-patterns

Context preview

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

Godot 4 Autoload单例模式最佳实践,包含全局管理、事件总线、信号通信。

SKILL.md

godot-autoload-patterns.SKILL.md
name: godot-autoload-patterns
description: Godot 4 Autoload单例模式最佳实践,包含全局管理、事件总线、信号通信。

Godot Autoload 单例模式

概述

Autoload(自动加载)是 Godot 中的单例功能,允许脚本在游戏开始时自动加载并在整个游戏周期中存在。正确使用 Autoload 可以有效管理全局状态和系统服务。

1. 全局数据管理

1.1 GameData 单例

# game_data.gd (Add to Project Settings > Autoload)
extends Node

enum GameState { MENU, PLAYING, PAUSED, GAME_OVER }

var state: GameState = GameState.MENU
var score: int = 0:
    set(value):
        score = value
        score_changed.emit(score)

var high_score: int = 0
var level: int = 1
var player_health: int = 100

func _ready() -> void:
    process_mode = Node.PROCESS_MODE_ALWAYS
    _load_high_score()

func _input(event: InputEvent) -> void:
    if event.is_action_pressed("pause") and state == GameState.PLAYING:
        toggle_pause()

func start_game() -> void:
    score = 0
    state = GameState.PLAYING
    game_started.emit()

func toggle_pause() -> void:
    var is_paused := state != GameState.PAUSED

    if is_paused:
        state = GameState.PAUSED
        get_tree().paused = true
    else:
        state = GameState.PLAYING
        get_tree().paused = false

    game_paused.emit(is_paused)

func end_game(won: bool) -> void:
    state = GameState.GAME_OVER

    if score > high_score:
        high_score = score
        _save_high_score()

    game_over.emit(won)

func add_score(points: int) -> void:
    score += points

func _load_high_score() -> void:
    if FileAccess.file_exists("user://high_score.save"):
        var file := FileAccess.open("user://high_score.save", FileAccess.READ)
        high_score = file.get_32()

func _save_high_score() -> void:
    var file := FileAccess.open("user://high_score.save", FileAccess.WRITE)
    file.store_32(high_score)

2. 事件总线模式

2.1 EventBus 单例

# event_bus.gd (Autoload)
extends Node

# Player events
signal player_spawned(player: Node2D)
signal player_died(player: Node2D)
signal player_health_changed(health: int, max_health: int)

# Enemy events
signal enemy_spawned(enemy: Node2D)
signal enemy_died(enemy: Node2D, position: Vector2)
signal wave_started(wave_number: int)

# Item events
signal item_collected(item_type: StringName, value: int)
signal powerup_activated(powerup_type: StringName)

# Level events
signal level_started(level_number: int)
signal level_completed(level_number: int, time: float)
signal checkpoint_reached(checkpoint_id: int)

# Game state events
signal game_paused(is_paused: bool)
signal game_over(won: bool)

2.2 使用示例

# 在任意脚本中连接信号
class_name Enemy
extends CharacterBody2D

func die() -> void:
    EventBus.enemy_died.emit(self, global_position)
    queue_free()
# 监听信号
class_name GameManager
extends Node

func _ready() -> void:
    EventBus.enemy_died.connect(_on_enemy_died)
    EventBus.level_started.connect(_on_level_started)

func _on_enemy_died(enemy: Node2D, position: Vector2) -> void:
    spawn_drops(position)
    add_score(10)

func _on_level_started(level_number: int) -> void:
    prepare_waves(level_number)

3. 服务管理器

3.1 AudioManager

# audio_manager.gd (Autoload)
extends Node

@export var bgm_bus: int = 0
@export var sfx_bus: int = 1

var _bgm_player: AudioStreamPlayer
var _sfx_player: AudioStreamPlayer

func _ready() -> void:
    _bgm_player = AudioStreamPlayer.new()
    _sfx_player = AudioStreamPlayer.new()
    add_child(_bgm_player)
    add_child(_sfx_player)

func play_bgm(stream: AudioStream, volume_db: float = 0.0) -> void:
    _bgm_player.stream = stream
    _bgm_player.volume_db = volume_db
    _bgm_player.play()

func play_sfx(stream: AudioStream, volume_db: float = 0.0) -> void:
    _sfx_player.stream = stream
    _sfx_player.volume_db = volume_db
    _sfx_player.play()

func stop_bgm() -> void:
    _bgm_player.stop()

3.2 SceneManager

# scene_manager.gd (Autoload)
extends Node

signal scene_loading_progress(progress: float)
signal scene_loaded(scene: Node)

var _current_scene: Node
var _loader: ResourceLoader

func _ready() -> void:
    _current_scene = get_tree().current_scene

func change_scene(scene_path: String) -> void:
    scene_loading_progress.emit(0.0)

    if ResourceLoader.has_cached(scene_path):
        var scene := load(scene_path) as PackedScene
        _swap_scene(scene.instantiate())
        return

    ResourceLoader.load_threaded_request(scene_path)

    while true:
        var progress := []
        var status := ResourceLoader.load_threaded_get_status(scene_path, progress)

        match status:
            ResourceLoader.THREAD_LOAD_IN_PROGRESS:
                scene_loading_progress.emit(progress[0])
                await get_tree().process_frame
            ResourceLoader.THREAD_LOAD_LOADED:
                var scene := ResourceLoader.load_threaded_get(scene_path) as PackedScene
                _swap_scene(scene.instantiate())
                return
            _:
                push_error("Failed to load scene: %s" % scene_path)
                return

func _swap_scene(new_scene: Node) -> void:
    if _current_scene:
        _current_scene.queue_free()

    _current_scene = new_scene
    get_tree().root.add_child(_current_scene)
    get_tree().current_scene = _current_scene
    scene_loaded.emit(_current_scene)

4. 场景结构

Project Settings > Autoload
├── GameData          # 全局游戏数据
├── EventBus         # 事件总线
├── AudioManager     # 音频管理
├── SceneManager     # 场景管理
├── SaveManager      # 存档管理
└── InputManager     # 输入管理

5. 设计原则

| 原则 | 说明 | |------|------| | **最小化原则** | 只将真正需要全局访问的对象设为 Autoload | | **单一职责** | 每个 Autoload 只负责一个功能 | | **信号解耦** | 优先使用 EventBus 信号通信 | | **避免滥用** | 过多 Autoload 会使代码耦合度增加 |

6. 注意事项

| 注意事项 | 说明 | |----------|------| | **初始化顺序** | Autoload 按配置顺序初始化 | | ** PROCESS_MODE_ALWAYS** | 需要在暂停时运行的脚本设置此模式 | | **避免循环依赖** | Autoload 之间不要相互引用形成循环 | | **线程安全** | 多线程场景注意信号线程安全 |

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 文件的操作方法。