mcpField
G
godot

godot

github.com/bfollington开发51118 次安装2 周前更新
代码仓库

关于 godot

godot 是面向 LLM 编码助手的 Godot Engine 游戏与应用开发技能,重点涵盖场景和资源文件格式、验证、架构模式、模板及测试流程。

主要功能

  1. 01.gd、.tscn 和 .tres 文件指导
  2. 02.tscn 与 .tres 验证脚本
  3. 03组件化与信号驱动模式
  4. 04可复用代码和资源模板
  5. 05GUT 单元测试指导

适用场景

  1. 01创建或编辑 Godot 场景与资源
  2. 02排查资源加载和语法错误
  3. 03构建组件化游戏系统
  4. 04使用 GUT 测试游戏逻辑

安装

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

$npx skills add https://github.com/bfollington/terma --skill godot

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/templates/
attribute_template.gd
component_template.gd
interaction_template.gd
item_resource.tres
spell_resource.tres
references/
architecture-patterns.md
common-pitfalls.md
file-formats.md
godot4-physics-api.md
scripts/
validate_tres.py
validate_tscn.py

详细介绍

Godot Engine 开发技能

专为使用 Godot Engine 开发游戏和应用提供的指导,重点关注 LLM 编码助手与 Godot 独特文件结构之间的高效协作。

概述

Godot 项目使用 GDScript 代码文件(.gd)和基于文本的资源文件(场景使用 .tscn,资源使用 .tres)。GDScript 简单易用,但资源文件有严格的格式要求,与 GDScript 语法有显著差异。本技能提供文件格式专业知识、经过验证的架构模式、验证工具、代码模板和调试工作流,助力高效开发 Godot 项目。

何时使用本技能

在以下情况调用本技能:

  • 处理任何 Godot Engine 项目
  • 创建或修改 .tscn(场景)或 .tres(资源)文件
  • 实现游戏系统(交互、属性、法术、物品栏等)
  • 调试“文件加载失败”或类似的资源错误
  • 设置基于组件的架构
  • 创建信号驱动系统
  • 实现基于资源的数据(物品、法术、技能)

关键原则

1. 了解文件格式差异

GDScript(.gd)——完整的编程语言:

extends Node
class_name MyClass

var speed: float = 5.0
const MAX_HEALTH = 100

func _ready():
    print("Ready")

场景文件(.tscn)——严格的序列化格式:

[ext_resource type="Script" path="res://script.gd" id="1"]

[node name="Player" type="CharacterBody3D"]
script = ExtResource("1")  # NOT preload()!

资源文件(.tres)——不支持 GDScript 语法:

[ext_resource type="Script" path="res://item.gd" id="1"]

[resource]
script = ExtResource("1")  # NOT preload()!
item_name = "Sword"        # NOT var item_name = "Sword"!
2. .tres 和 .tscn 文件的关键规则

在 .tres/.tscn 文件中绝对不要使用:

  • preload() ——改用 ExtResource("id")
  • var、const、func ——这些是 GDScript 关键字
  • 未指定类型的数组 ——使用 Array[Type]([...]) 语法

在 .tres/.tscn 文件中始终使用:

  • 外部资源使用 ExtResource("id")
  • 内联资源使用 SubResource("id")
  • 类型化数组:Array[Resource]([...])
  • 使用前先正确声明 ExtResource
3. 分离关注点

将逻辑放在 .gd 文件中,将数据放在 .tres 文件中:

src/
  spells/
    spell_resource.gd      # Class definition + logic
    spell_effect.gd        # Effect logic
resources/
  spells/
    fireball.tres          # Data only, references scripts
    ice_spike.tres         # Data only

这样可以让 LLM 编辑更安全、更清晰。

4. 基于组件的架构

将功能拆分为小型、专注的组件:

Player (CharacterBody3D)
├─ HealthAttribute (Node)     # Component
├─ ManaAttribute (Node)        # Component
├─ Inventory (Node)            # Component
└─ StateMachine (Node)         # Component
    ├─ IdleState (Node)
    ├─ MoveState (Node)
    └─ AttackState (Node)

优点:

  • 每个组件都是小型、专注的文件
  • 易于理解和修改
  • 职责明确
  • 可在不同实体之间复用
5. 信号驱动通信

使用信号实现松耦合:

# Component emits signals
signal health_changed(current, max)
signal death()

# Parent connects to signals
func _ready():
    $HealthAttribute.health_changed.connect(_on_health_changed)
    $HealthAttribute.death.connect(_on_death)

优点:

  • 系统之间没有紧密耦合
  • 易于添加新的监听器
  • 自说明(信号会显示可用事件)
  • 无需修改游戏逻辑,UI 就能连接信号

使用捆绑资源

验证脚本

在 Godot 中测试之前,先验证 .tres 和 .tscn 文件,以便及早发现语法错误。

验证 .tres 文件:

python3 scripts/validate_tres.py resources/spells/fireball.tres

验证 .tscn 文件:

python3 scripts/validate_tscn.py scenes/player/player.tscn

在以下情况使用这些脚本:

  • 以编程方式创建或编辑 .tres/.tscn 文件后
  • 调试“加载失败”错误时
  • 提交场景/资源变更前
  • 用户报告自定义资源存在问题时
参考文档

需要详细信息时,加载参考文件:

references/file-formats.md ——深入介绍 .gd、.tscn、.tres 语法:

  • 各类文件的完整语法规则
  • 常见错误及示例
  • 安全与高风险编辑模式
  • ExtResource 和 SubResource 的用法

references/architecture-patterns.md ——经过验证的架构模式:

  • 基于组件的交互系统
  • 属性系统(生命值、法力值等)
  • 基于资源的效果系统(法术、物品)
  • 物品栏系统
  • 状态机模式
  • 组合使用多种模式的示例

在以下情况阅读这些参考资料:

  • 实现新的游戏系统时
  • 不确定 .tres/.tscn 语法时
  • 调试文件格式错误时
  • 为新功能规划架构时
代码模板

使用模板作为常见模式的起点。模板位于 assets/templates/:

component_template.gd - 包含信号、导出变量和激活逻辑的基础组件:

# Copy and customize for new components
cp assets/templates/component_template.gd src/components/my_component.gd

attribute_template.gd - 数值属性(生命值、法力值、耐力):

# Use for any numeric attribute with min/max
cp assets/templates/attribute_template.gd src/attributes/stamina_attribute.gd

interaction_template.gd - 交互组件基类:

# Extend for custom interactions (pickup, door, switch, etc.)
cp assets/templates/interaction_template.gd src/interactions/lever_interaction.gd

spell_resource.tres - 包含效果的法术示例:

# Use as reference for creating new spell data
cat assets/templates/spell_resource.tres

item_resource.tres - 物品资源示例:

# Use as reference for creating new item data
cat assets/templates/item_resource.tres

工作流

工作流 1:创建新的组件系统

示例:为敌人添加生命值系统。

步骤:

  1. 阅读架构模式参考:

    # Check for similar patterns
    Read references/architecture-patterns.md
    # Look for "Attribute System" section
    
  2. 使用模板创建基类:

    cp assets/templates/attribute_template.gd src/attributes/attribute.gd
    # Customize the base class
    
  3. 创建专用子类:

    # Create health_attribute.gd extending attribute.gd
    # Add health-specific signals (damage_taken, death)
    
  4. 通过编辑 .tscn 将其添加到场景中:

    [ext_resource type="Script" path="res://src/attributes/health_attribute.gd" id="4_health"]
    
    [node name="HealthAttribute" type="Node" parent="Enemy"]
    script = ExtResource("4_health")
    value_max = 50.0
    value_start = 50.0
    
  5. 立即在 Godot 编辑器中测试

  6. 如果出现问题,验证场景文件:

    python3 scripts/validate_tscn.py scenes/enemies/base_enemy.tscn
    
工作流 2:创建资源数据文件(.tres)

示例:创建新的法术。

步骤:

  1. 参考模板:

    cat assets/templates/spell_resource.tres
    
  2. 按正确结构创建新的 .tres 文件:

    [gd_resource type="Resource" script_class="SpellResource" load_steps=3 format=3]
    
    [ext_resource type="Script" path="res://src/spells/spell_resource.gd" id="1"]
    [ext_resource type="Script" path="res://src/spells/spell_effect.gd" id="2"]
    
    [sub_resource type="Resource" id="Effect_1"]
    script = ExtResource("2")
    effect_type = 0
    magnitude_min = 15.0
    magnitude_max = 25.0
    
    [resource]
    script = ExtResource("1")
    spell_name = "Fireball"
    spell_id = "fireball"
    mana_cost = 25.0
    effects = Array[ExtResource("2")]([SubResource("Effect_1")])
    
  3. 测试前进行验证:

    python3 scripts/validate_tres.py resources/spells/fireball.tres
    
  4. 修复验证器报告的所有错误

  5. 在 Godot 编辑器中测试

工作流 3:调试资源加载问题

当用户报告“资源加载失败”或类似错误时。

步骤:

  1. 阅读错误中指出的文件:

    # Check file syntax
    Read resources/spells/problem_spell.tres
    
  2. 运行验证脚本:

    python3 scripts/validate_tres.py resources/spells/problem_spell.tres
    
  3. 检查常见错误:

    • 使用 preload() 而不是 ExtResource()
    • 使用 var、const、func 关键字
    • 缺少 ExtResource 声明
    • 数组语法不正确(未指定类型)
  4. 如有需要,阅读文件格式参考:

    Read references/file-formats.md
    # Focus on "Resource Files (.tres)" section
    # Check "Common Mistakes Reference"
    
  5. 修复错误并重新验证

工作流 4:根据架构模式实现功能

实现已知模式(交互系统、状态机等)时。

步骤:

  1. 阅读相关模式:

    Read references/architecture-patterns.md
    # Find the specific pattern (e.g., "Component-Based Interaction System")
    
  2. 复制相关模板:

    cp assets/templates/interaction_template.gd src/interactions/door_interaction.gd
    
  3. 自定义模板:

    • 重写 _perform_interaction()
    • 添加用于配置的自定义导出变量
    • 如有需要,添加自定义信号
  4. 按照模式创建场景结构:

    [node name="Door" type="StaticBody3D"]
    script = ExtResource("base_interactable.gd")
    
    [node name="DoorInteraction" type="Node" parent="."]
    script = ExtResource("door_interaction.gd")
    interaction_text = "Open Door"
    
  5. 逐步测试

使用 GUT 进行单元测试

使用 GUT(Godot 单元测试)测试纯逻辑——任何不依赖场景树的 RefCounted 或 Resource 类都适合作为测试对象。例如卡牌系统、计分、状态机、地图生成器、挑战逻辑等。

安装
  1. 从 GitHub releases 下载(v9.5.0 适用于 Godot 4.5;v9.6.0+ 需要更新版本的 Godot)
  2. 将 addons/gut/ 放入项目中
  3. 在“项目设置” →“插件”中启用插件
  4. 在项目根目录创建 .gutconfig.json:
{
  "dirs": ["res://test/unit"],
  "prefix": "test_",
  "suffix": ".gd",
  "log_level": 1
}
编写测试

测试文件位于 test/unit/,文件名以 test_ 开头,并继承 GutTest:

extends GutTest

func test_score_calculation() -> void:
    var scoring := Scoring.new()
    assert_eq(scoring.calculate(3, 0), 100, "Base score for 3 moves")
    assert_gt(scoring.calculate(2, 0), scoring.calculate(3, 0), "Fewer moves = higher score")

func test_deck_shuffle() -> void:
    var rng := RandomNumberGenerator.new()
    rng.seed = 42
    var deck := CardSystem.create_shuffled_deck(rng)
    assert_eq(deck.size(), 52, "Full deck")

主要约定:

  • 测试方法必须以 test_ 开头
  • 辅助方法使用 _ 前缀(不会被识别为测试)
  • 使用 before_each() / after_each() 进行设置和清理
  • 关键断言:assert_eq、assert_ne、assert_true、assert_false、assert_gt、assert_lt、assert_null、assert_not_null
运行测试
# Run all tests (returns exit code 0 on pass, 1 on fail)
godot -d -s --path "$PWD" addons/gut/gut_cmdln.gd -gexit

# Run a specific test file
godot -d -s --path "$PWD" addons/gut/gut_cmdln.gd -gtest=res://test/unit/test_scoring.gd -gexit

# Run tests matching a pattern
godot -d -s --path "$PWD" addons/gut/gut_cmdln.gd -gdir=res://test/unit -gselect=weekly -gexit
测试内容

优先测试继承自 RefCounted 或 Resource 的纯逻辑类:

  • 游戏规则和计分
  • 卡牌/牌组/手牌管理
  • 地图生成(验证属性,而非精确输出)
  • 状态快照/恢复
  • 升级/进度计算

避免在单元测试中测试依赖场景树的代码(渲染、UI、输入处理)。

常见问题与解决方案

问题 1:在 .tres 文件中使用 GDScript 语法

问题:

# ❌ WRONG
script = preload("res://script.gd")
var items = [1, 2, 3]

解决方案:

# ✅ CORRECT
[ext_resource type="Script" path="res://script.gd" id="1"]
script = ExtResource("1")
items = Array[int]([1, 2, 3])

预防: 测试前运行验证脚本。

问题 2:缺少 ExtResource 声明

问题:

[resource]
script = ExtResource("1_script")  # Not declared!

解决方案:

[ext_resource type="Script" path="res://script.gd" id="1_script"]

[resource]
script = ExtResource("1_script")

检测: 验证脚本会检测到此问题。

陷阱 3:编辑复杂的 .tscn 层级结构

问题: 修改实例化场景的子节点可能会在编辑器重新保存时出错。

解决方案:

  • 只在 .tscn 文件中修改简单属性
  • 复杂修改请使用 Godot 编辑器
  • 文本编辑后立即测试
  • 使用 git 跟踪更改,并在需要时还原
陷阱 4:.tres 文件中的未类型化数组

问题:

effects = [SubResource("Effect_1")]  # Missing type

解决方案:

effects = Array[Resource]([SubResource("Effect_1")])

预防: 验证脚本会对此发出警告。

陷阱 5:忘记覆盖实例属性

问题: 实例化场景时,忘记覆盖子节点属性。实例会使用默认值(通常为 null),导致难以察觉的错误。

# level.tscn
[node name="KeyPickup" parent="." instance=ExtResource("6_pickup")]
# Oops! PickupInteraction.item_resource is null - pickup won't work!

解决方案: 始终使用 index 语法配置实例化场景的属性:

[node name="KeyPickup" parent="." instance=ExtResource("6_pickup")]

[node name="PickupInteraction" parent="KeyPickup" index="0"]
item_resource = ExtResource("7_key")

检测:

  • 立即在游戏中测试该实例
  • 阅读 references/file-formats.md 中的“实例属性覆盖”部分,了解详情
  • 创建场景实例时,先问自己:“此场景是否有需要设置属性的可配置组件?”

预防: 实例化任何带有可配置子节点(PickupInteraction、DoorInteraction 等)的场景后,始终确认关键属性已被覆盖。

陷阱 6:CPUParticles3D 的 color_ramp 不显示颜色

问题: 为 CPUParticles3D 设置了 color_ramp,但粒子仍呈白色或不显示渐变颜色。

[node name="CPUParticles3D" type="CPUParticles3D" parent="."]
mesh = SubResource("SphereMesh_1")
color_ramp = SubResource("Gradient_1")  # Gradient is set but doesn't work!

根本原因: 网格需要使用 vertex_color_use_as_albedo = true 的材质,才能将粒子颜色应用到网格表面。

解决方案: 为网格添加启用了顶点颜色的 StandardMaterial3D:

[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
vertex_color_use_as_albedo = true

[sub_resource type="SphereMesh" id="SphereMesh_1"]
material = SubResource("StandardMaterial3D_1")
radius = 0.12
height = 0.24

[node name="CPUParticles3D" type="CPUParticles3D" parent="."]
mesh = SubResource("SphereMesh_1")
color_ramp = SubResource("Gradient_1")  # Now works!

预防: 创建带有 color 或 color_ramp 的 CPUParticles3D 时,始终为网格添加 vertex_color_use_as_albedo = true 的材质。

最佳实践

1. 查阅常见问题参考文档

遇到问题时,请查阅参考文档:

references/common-pitfalls.md - 常见的 Godot 易错点及解决方案:

  • 初始化和 @onready 时序问题
  • 节点引用和 get_node() 问题
  • 信号连接问题
  • 资源加载和修改
  • CharacterBody3D 移动
  • 变换和基向量混淆
  • 输入处理
  • 类型安全问题
  • 场景实例化陷阱
  • Tween 问题

references/godot4-physics-api.md - 物理 API 速查:

  • 正确的射线检测 API(PhysicsRayQueryParameters3D)
  • 形状查询和碰撞检测
  • 碰撞层和遮罩
  • Area3D、RigidBody3D 与 CharacterBody3D 的区别
  • 常见物理模式
  • 性能提示

遇到以下情况时,请加载这些文档:

  • 出现空引用错误
  • 实现物理/碰撞系统
  • 调试 @onready 时序问题
  • 使用 CharacterBody3D 移动
2. 编辑 .tres/.tscn 后务必验证
python3 scripts/validate_tres.py path/to/file.tres
python3 scripts/validate_tscn.py path/to/file.tscn
2. 使用模板作为起点

不要从头编写组件,而应改编模板:

cp assets/templates/component_template.gd src/my_component.gd
3. 查阅参考文档了解详细语法

不确定语法时,请加载参考文档:

Read references/file-formats.md
4. 遵循关注点分离
  • 逻辑 → .gd 文件
  • 数据 → .tres 文件
  • 场景结构 → .tscn 文件(复杂修改优先使用编辑器)
5. 使用信号进行通信

优先使用信号,而不是直接调用方法:

# ✅ Good - Loose coupling
signal item_picked_up(item)
item_picked_up.emit(item)

# ❌ Avoid - Tight coupling
get_parent().get_parent().add_to_inventory(item)
6. 增量测试

每次更改后:

  1. 使用脚本验证
  2. 在 Godot 编辑器中测试
  3. 验证功能
  4. 提交到 git
7. 多使用导出变量

让配置清晰可见且可编辑:

@export_group("Movement")
@export var speed: float = 5.0
@export var jump_force: float = 10.0

@export_group("Combat")
@export var damage: int = 10

使用 Godot 命令行工具

可使用 godot 命令行工具运行游戏并执行各种操作,无需打开编辑器。

运行游戏

运行当前项目:

godot --path . --headless

运行指定场景:

godot --path . --scene scenes/main_menu.tscn

使用调试标志运行:

# Show collision shapes
godot --path . --debug-collisions

# Show navigation debug visuals
godot --path . --debug-navigation

# Show path lines
godot --path . --debug-paths
检查/验证代码

检查 GDScript 语法,但不运行:

godot --path . --check-only --script path/to/script.gd

运行无头测试(用于自动化测试):

godot --path . --headless --quit --script path/to/test_script.gd
两个看起来像真实错误的无头模式陷阱

新建的 class_name 在重新导入项目前无法通过 --check-only。 无头检查会从项目缓存的类列表中解析全局类,而该列表尚未包含你刚创建的脚本。表现出来的是一个看似确凿、实则错误的解析错误:

Parse Error: Identifier "MyNewClass" not declared in the current scope

修复一次,然后重新检查:

godot --path . --import --headless --quit

在充满 static func 工具类的代码库中,这个问题最棘手:新类型会同时在多个文件中被引用,错误看起来就像确实缺少依赖项。

沙盒化 Agent shell 中的无头 Godot 崩溃或挂起。 如果进程无法写入 user://logs/...,就会因 handle_crash: Program crashed with signal 11 退出,或因 XPC Connection Invalid 而挂起——测试运行器设置的超时会将其变成空输出和非零退出码。这两种情况看起来都像被测代码中的真实缺陷,也会按真实缺陷来调试;但问题其实只是文件系统访问被拒。应在首次启动时就禁用沙盒运行 Godot,而不是等出现令人困惑的回溯后再处理;也要提前告知子 Agent——它们会各自独立遇到这个问题,每个都会因此浪费同样的半小时。

通过 CLI 执行编辑器操作

不打开编辑器导入资源:

godot --path . --import --headless --quit

导出项目:

# Export release build
godot --path . --export-release "Preset Name" builds/game.exe

# Export debug build
godot --path . --export-debug "Preset Name" builds/game_debug.exe
常见 CLI 工作流

工作流:快速运行测试

# Run the project and quit after testing
godot --path . --quit-after 300  # Runs for 300 frames then quits

工作流:自动导入资源

# Import all resources and exit (useful in CI/CD)
godot --path . --import --headless --quit

工作流:脚本验证

# Validate a GDScript file before committing
godot --path . --check-only --script src/player/player.gd

工作流:无头服务器

# Run as dedicated server (no rendering)
godot --path . --headless --scene scenes/multiplayer_server.tscn
CLI 使用技巧
  1. 从项目目录运行时,始终指定 --path .,确保 Godot 能找到 project.godot
  2. 在 CI/CD 和自动化测试中使用 --headless(不显示窗口、不渲染)
  3. 使用 --quit 或 --quit-after N,在任务完成后自动退出
  4. 将 --check-only 与 --script 搭配使用,快速验证 GDScript 语法
  5. 使用调试标志(--debug-collisions、--debug-navigation),在开发时可视化系统
  6. 检查退出码——非零表示存在错误(对 CI/CD 脚本很有用)
示例:用于验证 GDScript 的提交前钩子
#!/bin/bash
# Validate all changed .gd files before committing

for file in $(git diff --cached --name-only --diff-filter=ACM | grep '\.gd$'); do
    if ! godot --path . --check-only --script "$file" --headless --quit; then
        echo "GDScript validation failed for $file"
        exit 1
    fi
done

快速参考

文件类型决策树

编写游戏逻辑? → 使用 .gd 文件

存储数据(物品属性、法术配置)? → 使用 .tres 文件

创建场景结构? → 使用 .tscn 文件(复杂结构优先使用 Godot 编辑器)

语法快速检查

在 .gd 文件中: 完整的 GDScript——var、func、preload() 等 ✅

在 .tres/.tscn 文件中:

  • preload() ❌ → 使用 ExtResource("id") ✅
  • var、const、func ❌ → 仅使用属性值 ✅
  • [1, 2, 3] ❌ → 使用 Array[int]([1, 2, 3]) ✅
各验证脚本的适用场景

validate_tres.py——用于资源文件:

  • 物品、法术、技能
  • 自定义资源数据
  • 创建 .tres 文件后

validate_tscn.py——用于场景文件:

  • 玩家、敌人、关卡
  • UI 场景
  • 编辑 .tscn 文件后
各参考文档的适用场景

file-formats.md——适用于:

  • 创建或编辑 .tres/.tscn 文件
  • 遇到“failed to load”错误
  • 不确定语法规则

architecture-patterns.md——适用于:

  • 实现新的游戏系统
  • 规划组件结构
  • 查找经过验证的模式

总结

通过以下方式高效处理 Godot 项目:

  1. 理解文件格式——.gd 是代码,.tres/.tscn 是遵循严格语法的数据
  2. 使用验证工具——在测试前发现错误
  3. 遵循模式——使用参考资料中的成熟架构
  4. 从模板开始——在现有基础上调整,而不是从头创建
  5. 增量测试——频繁验证、测试和提交

关键在于:只要遵循 GDScript 与资源序列化格式之间的语法差异,Godot 的基于文本的文件就很适合大模型处理。

评论

支持 Markdown