Godot 4 Autoload单例模式最佳实践,包含全局管理、事件总线、信号通信。
Scanned 9/12/2026
Install to Claude Code
npx -y skills add 925236118/AlphaAgent --skill godot-autoload-patterns --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Godot Autoload Patterns?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/925236118-godot-autoload-patterns)More formats (shields.io, HTML) on the badges page.
---
name: godot-autoload-patterns
description: Godot 4 Autoload单例模式最佳实践,包含全局管理、事件总线、信号通信。
---
# Godot Autoload 单例模式
## 概述
Autoload(自动加载)是 Godot 中的单例功能,允许脚本在游戏开始时自动加载并在整个游戏周期中存在。正确使用 Autoload 可以有效管理全局状态和系统服务。
## 1. 全局数据管理
### 1.1 GameData 单例
```gdscript
# 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 单例
```gdscript
# 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 使用示例
```gdscript
# 在任意脚本中连接信号
class_name Enemy
extends CharacterBody2D
func die() -> void:
EventBus.enemy_died.emit(self, global_position)
queue_free()
```
```gdscript
# 监听信号
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
```gdscript
# 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
```gdscript
# 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 之间不要相互引用形成循环 |
| **线程安全** | 多线程场景注意信号线程安全 |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!