mcpField
G
godot-nodes-scenes

godot-nodes-scenes

github.com/gamedev-skills开发5.4k7.2k 次安装今天更新
代码仓库

关于 godot-nodes-scenes

面向 Godot 4.7 开发者的技能,讲解场景结构、节点树组合和运行时实例管理。内容涵盖可复用 PackedScene 工作流、自动加载,以及安全访问节点,并附带用于检查项目引用的 Python 工具。

主要功能

  1. 01场景与节点组合
  2. 02运行时实例化 PackedScene
  3. 03安全访问与清理节点
  4. 04自动加载设置指引
  5. 05Python 项目引用检查器

适用场景

  1. 01构建可复用的游戏功能
  2. 02运行时生成子弹或敌人
  3. 03排查缺失或已释放的节点
  4. 04检查场景和资源引用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill godot-nodes-scenes

安装后在 Claude Code 中输入/godot-nodes-scenes确认已加载。

附带文件references/tree-and-instancing.mdscripts/check_godot_project.py

详细介绍

Godot 节点与场景(4.x)

通过节点和场景组合游戏,在运行时实例化它们,并安全访问场景树,避免因节点已释放或缺失而崩溃。目标版本为 Godot 4.7。

适用场景

  • 用于构建 .tscn 场景、选择如何将功能拆分为节点、实例化 PackedScene(子弹、敌人、UI),或设置自动加载单例。
  • 用于调试 get_node() / $Path 返回 null,或“Attempt to call on a previously freed instance”错误。

不适用场景: GDScript 语言/语法 → godot-gdscript;基于信号的解耦 → godot-signals-groups;物理主体/碰撞 → godot-physics。

核心工作流

  1. 通过组合建模。 场景是保存为 .tscn 的节点树。构建小型、用途单一的场景(Player、Bullet、Enemy),并由它们组合成更大的场景。优先添加子节点,而不是深层继承。
  2. 让场景可复用: 为根节点添加脚本,并公开 @export 配置。保存后,它就成为可多次实例化的 PackedScene。
  3. 在运行时实例化: 使用 preload/load → scene.instantiate() → add_child(instance)。添加后设置位置/状态(添加前设置也可以)。
  4. 安全访问节点。 对固定子节点使用 @onready var x = $Path;对树中深层节点使用唯一名称(%Name);绝不要假设节点仍然存在。
  5. 使用自动加载处理全局状态/服务(游戏状态、音频、场景切换)——在“项目设置” > “全局”(自动加载)中注册后,即可在任何地方按名称访问。
  6. 使用 queue_free() 释放节点,并在之后访问时通过 is_instance_valid() 检查。
  7. 完成前检查引用。 创建、移动或重命名场景、资源或脚本后,运行 python scripts/check_godot_project.py <project-dir>(无需安装 Godot;使用 --json 可获取机器可读的输出)。修复所有 ERROR(缺失或大小写错误的 res:// 路径、未声明的 ExtResource/SubResource ID、错误的 parent= 路径、缺失的主场景或自动加载项),并重新运行,直到退出代码为 0。Godot 仍可通过 UID 找到的过时 path= 等警告不会造成问题,但值得修复。请从此技能目录运行脚本路径,或先解析已安装的技能路径。脚本需要 Python 3.10+,且不需要其他依赖;它不能替代在 Godot 中打开项目。

常见模式

1. 在运行时实例化场景
extends Node2D

const BULLET := preload("res://bullet.tscn")   # preload: loaded at compile time

func shoot(at: Vector2, dir: Vector2) -> void:
    var bullet := BULLET.instantiate()         # create an instance of the scene
    bullet.global_position = at
    bullet.direction = dir                      # set exported/public state
    add_child(bullet)                           # now it's in the tree and runs
2. 安全访问节点:$、get_node_or_null 和唯一名称
@onready var label: Label = $UI/Label            # $ is sugar for get_node("UI/Label")
@onready var health_bar: ProgressBar = %HealthBar # % = scene-unique name (rename-proof)

func update() -> void:
    var optional := get_node_or_null("Maybe/Missing")  # returns null instead of erroring
    if optional:
        optional.queue_free()
3. 自动加载单例(全局游戏状态)
# game_state.gd — add in Project Settings > Globals > Autoload as "GameState".
extends Node

var score := 0
signal score_changed(value: int)

func add_score(points: int) -> void:
    score += points
    score_changed.emit(score)         # any scene can: GameState.score_changed.connect(...)
4. 切换运行中的场景
func go_to_level_2() -> void:
    # Swaps the current scene for another. Frees the old scene tree.
    get_tree().change_scene_to_file("res://levels/level_2.tscn")
    # Or, with a preloaded PackedScene:
    # get_tree().change_scene_to_packed(LEVEL_2)

易错点

  • $Path / get_node() 返回 null 或报错: 路径错误,或节点尚未进入场景树。使用 @onready,确认路径与场景匹配,或对可选节点使用 get_node_or_null()。
  • 重命名节点会导致 $Path 失效。 使用唯一名称(%Name,通过右键菜单 > “设为唯一名称访问”设置),让深层引用在重命名和重新设定父节点后仍然有效。
  • 在帧中途调用 free() 可能导致其他仍在使用该节点的代码崩溃。 优先使用 queue_free()(在帧结束时删除),并检查 is_instance_valid(node)。
  • 在调用 add_child() 前设置子节点状态没有问题,但子节点的 _ready() 只会在它进入场景树后运行——不要指望在那之前就能使用它的 @onready 变量。
  • 自动加载顺序很重要: 自动加载项会按列表顺序添加到主场景之前。自动加载项不能依赖主场景已经存在。
  • instance() 在 Godot 4 中更名为 instantiate()。 preload 在解析时运行(路径必须是常量);load 在运行时运行(路径可以是变量)。
  • change_scene_to_file() 是延迟执行的,并非立即执行——Godot 会在当前帧结束时切换场景并释放旧场景。调用后,后续代码仍会针对旧场景树运行;get_tree().current_scene 也要到下一帧才会指向新场景。不要在同一行读取新场景的节点;应在新场景的 _ready() 中读取。

参考资料

  • 有关场景继承、从代码保存场景时的 owner/所有权、组与唯一名称,以及节点路径的特殊情况,请阅读 references/tree-and-instancing.md。
  • scripts/check_godot_project.py — 用于 Godot 4.x 项目的只读参考检查器;--help 会列出所有检查项和退出代码。

相关技能

  • godot-gdscript — 语言、生命周期和 @onready。
  • godot-signals-groups — 将实例化场景与其生成器解耦。
  • godot-resources — 在实例之间共享数据,避免重复。
  • save-systems — 跨运行持久化场景/游戏状态。

评论

支持 Markdown