← ClaudeAtlas

godot-gdscriptlisted

写 Godot(GDScript/C#)时使用。节点树、signal、场景、性能规范。
Wade-DevCode/awesome-coding-skills-cn · ★ 3 · AI & Automation · score 78
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# Godot ## 何时用 - 新建或修改任何 GDScript 脚本或 C# 组件脚本时。 - 节点间通信方式有疑问(是用 get_node、直接引用还是 signal)时。 - `_process` 和 `_physics_process` 里的逻辑越写越多、帧率下降时。 - 场景实例化、资源加载/释放方式不确定时。 - 遇到内存泄漏、孤立节点、信号未断开等问题时。 ## 核心规则 ### 1. 节点与场景:@onready 缓存,场景实例化代替继承 **规则:** 节点引用用 `@onready` 在 `_ready()` 阶段一次性缓存;不在 `_process` 里反复 `get_node()`;复用结构用场景实例化,而不是多层继承。 **为什么——真实会犯的错:** 在 `_process(delta)` 里每帧写 `$AnimationPlayer.play("run")`,GDScript 每次都要解析节点路径字符串、在节点树里做查找,场景节点数量一多(几百个)帧率肉眼可见地跌。另一个常见错误:用继承堆叠 Enemy → FlyingEnemy → BossEnemy → FinalBoss,四层下来 `_ready` 调用顺序、信号连接变得极难追踪,改一层上面全乱。 **怎么做:** - 节点引用用 `@onready var anim: AnimationPlayer = $AnimationPlayer`,只在 `_ready()` 时解析一次路径,后续直接用变量。 - 逻辑上独立、可复用的结构拆成独立场景(`.tscn`),用 `instantiate()` 生成,而不是靠继承叠加。 - `get_node()` 只在 `_ready()`、事件回调里调用,**不放进 `_process` 或 `_physics_process`**。 --- ### 2. signal 解耦:通信走信号,连接必须断开 **规则:** 节点间跨层通信用 `signal`;子节点不直接持有父节点引用;场景卸载或节点销毁前断开信号连接,防止内存泄漏和空引用回调。 **为什么——真实会犯的错:** Enemy 脚本里写了 `get_parent().get_node("HUD").show_damage(damage)`,这条路径硬绑了节点树结构,一旦 HUD 改了层级或名称,运行时立刻报 `null`,且错误信息只提示"尝试调用 null 上的方法",找来找去才发现是节点路径变了。另一个事故:动态生成的子弹连接了 GameManager 的信号,子弹 `queue_free()` 后没有断开,GameManager 还保持对已销毁节点的引用,触发回调时崩溃或静默错误。 **怎么做:** - 子节点向上通信 → 发射 `signal`,父节点监听,子节点不引用父节点。 - 跨系统通信 → 用 Autoload(单例)中转,或通过 signal bus。 - 动态节点连接信号时,在 `_exit_tree()` 或 `queue_free()` 前调用 `signal.disconnect(callback)` 断开。 - 用 `connect(..., CONNECT_ONE_SHOT)` 处理只触发一次的事件,自动断开更安全。 --- ### 3. _process vs _physics_process:物理归物理,能事件驱动就不轮询 **规则:** 涉及物理体、碰撞、速度的逻辑一律放 `_physics_p