godot-gdscript
Skill3 starsChanged 19 days agoMITView on GitHub
写或改 GDScript 时用。静态类型 := 与 Array[T] Dictionary[K, V]、class_name、@export @onready、信号 connect emit lambda、await 协程、match、setter getter、call_deferred、警告设置。GDScript typing, signals, coroutine, warnings.
4 other projects use a version of this.
Adopted by
Most recently taken up by
- Wade-DevCode/awesome-coding-skills-cntheir own version, first seen Nov 8, 2026
- gamedev-skills/awesome-gamedev-agent-skillstheir own version, first seen Oct 23, 2026
- gosomea/dsh-godot-aitheir own version, first seen Oct 8, 2026
- fetasty/godot-skillstheir own version, first seen May 16, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- gamedev-skills/awesome-gamedev-agent-skills★ 6.4ksame name
- fetasty/godot-skills★ 29same name
- gosomea/dsh-godot-ai★ 9same name
- Wade-DevCode/awesome-coding-skills-cn★ 7same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository18 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- godot-2d-in-3dSkill
- godot-2dSkill
- godot-3dSkill
- godot-animationSkill
- godot-audioSkill
- godot-builtin-firstSkill
- godot-csharpSkill
- godot-editor-toolingSkill
- godot-headless-testingSkill
- godot-inputSkill
- godot-multiplayerSkill
- godot-performanceSkill
- godot-resources-dataSkill
- godot-scene-architectureSkill
- godot-scene-authoringSkill
- godot-shaders-vfxSkill
- godot-uiSkill
The file
Files
GDScript 写法
GDScript 语言层的写法与陷阱:类型、注解、信号、协程、对象有效性、警告。断言与日志见 references/syntax.md。目标 4.7,最低 4.4,更新的特性标版本号。
范围
| 不含 | 去哪 |
| 节点选型、场景组织、节点通信 | godot-scene-architecture |
| 数据资源 | godot-resources-data |
| C# 写法 | godot-csharp |
| 卡顿与每帧分配 | godot-performance |
| 无头加载脚本、抓警告 | godot-headless-testing |
先查内置
| 需求 | 用这个 | 别自己写 |
| 延时一次 | await get_tree().create_timer(t).timeout 或 Timer 节点 | _process 里累加 delta |
| 周期执行 | Timer 节点的 timeout 信号 | _process 里 if elapsed > 0.5 |
| 输入轴 | Input.get_vector()、Input.get_axis() | 手写正负键相减 |
| 数值靠近目标 | move_toward()、lerp()、Tween | 手写 SmoothDamp |
| 取子节点 | %Name、@export var x: Node、@onready | 长硬路径 get_node("../../A/B") |
| 枚举名字互转 | State.keys()、State.find_key(v)、State["RUN"] | match 字符串表 |
| 数组变换 | filter map reduce any all pick_random sort_custom | for 加临时数组 |
| 随机 | randi_range()、randf_range()、RandomNumberGenerator | 自写 LCG |
| 浮点比较 | is_equal_approx()、is_zero_approx() | == 比较浮点 |
| 帧末调用 | callable.call_deferred()、set_deferred() | 用 Timer 凑一帧 |
| 数据放 Inspector 里改 | Resource 子类加 @export | JSON 手写解析 |
做法
静态类型
<!-- check: gdonly -->extends Node
var speed: float = 200.0
var hp := 10
var names: Array[String] = []
var scores: Dictionary[StringName, int] = {}
var target: Node2D
func take_damage(amount: int) -> bool:
hp -= amount
return hp <= 0
func _ready() -> void:
var raw: Dictionary = {"k": 1}
var value: int = raw["k"]
var sprite := get_node_or_null("Sprite") as Sprite2D
print(value, sprite)| 写法 | 结果 | 改法 |
:= 右值是 Variant,如无类型 Dictionary 取值、call() | 错误 inference_on_variant | var v: int = raw["k"] |
var x := max(a, b) | 同上,clamp min max lerp abs sign floor ceil round snapped 都返回 Variant | 用 maxf clampi 这类带类型版本 |
load(path) | 返回 Resource | var tex: Texture2D = load(path),常量路径用 preload() |
$Node、get_node() | 返回 Node | @onready var sprite: Sprite2D = $Sprite |
x as Sprite2D 类型不符 | 静默得 null | 只在就要这个结果时用 |
map() 结果赋给 Array[T] | 报错,map() 返回无类型 Array | typed.assign(untyped) |
| 整数传给枚举参数 | int_as_enum_without_cast | 写成员名或显式转换 |
Array[T]运行时强制元素类型,filter()保留元素类型Dictionary[K, V]4.4+,不支持再嵌套类型- 循环变量写类型:
for n: Node in nodes: - 大量数值用
PackedFloat32Array,Array[float]仍是 Variant 数组 - 对象类型可为
null,数值与字符串类型不可
class_name 与 preload
class_name Foo注册全局类,任何脚本可直接当类型和构造- 类名不能与 autoload 同名,报
Class "Foo" hides an autoload singleton - 类名不能与引擎类同名
- 无
class_name的脚本用常量引用,preload参数须是常量字符串 - 路径运行时才定用
load()
<!-- check: skip; gdonly -->const Rifle := preload("res://weapons/rifle.gd")
var main_weapon: Rifle = Rifle.new()- 两个脚本互相
preload在 4.7 可加载,仍建议用class_name打断环 @export类型只能是内置类型、Resource、Node、枚举- 3.x 的
export varonready varyieldconnect("sig", obj, "method")在 4.x 都没了
注解
<!-- check: gdonly -->extends Node2D
@export var speed: float = 200.0
@export_range(0.0, 1.0, 0.01) var ratio := 0.5
@export_enum("Idle", "Run") var mode: int = 0
@export_file("*.tscn") var next_scene: String
@export var bullet_scene: PackedScene
@export var spawn_point: Marker2D
@export_flags_2d_physics var hit_mask: int
@export_group("Loot")
@export var drops: Array[Resource] = []
@onready var label: Label = %Label
@onready var timer: Timer = $Timer
func _ready() -> void:
timer.start()
label.text = str(speed)全表见 references/annotations.md。
| 时刻 | 发生 |
| 声明初值 | 脚本默认值 |
_init() | 读到的是默认值 |
| 场景保存的值赋入 | 导出变量的 setter 此时调用,@onready 变量仍是 null |
@onready 赋值 | 紧接着 _ready() |
@export的类型来自标注或默认值,都没有是解析错误,要 Variant 写: Variant@export var n: Node只在 Node 派生脚本里可用- setter 里用节点前判断
is_node_ready() @onready与@export同用是错误onready_with_export- 成员默认值里用
$不带@onready是错误get_node_default_without_onready - 代码
add_child()的节点直接赋成员,不需要@onready - 场景里已存的属性值覆盖脚本的新默认值
- 导出
Resource随场景一起加载,大资源用@export_file存路径,用时load() - 4.5+
@export_file存 UID,要原始路径用@export_file_path @export_tool_button("名字")4.4+,须配@tool
信号
<!-- check: gdonly -->extends Node
signal died
signal damaged(amount: int, source: Node)
@export var button: Button
func _ready() -> void:
button.pressed.connect(_on_pressed)
damaged.connect(_log_damage.bind("player"))
died.connect(queue_free, CONNECT_ONE_SHOT)
func _on_pressed() -> void:
damaged.emit(3, self)
func _log_damage(amount: int, _source: Node, tag: String) -> void:
print(tag, amount)bind()的参数追加在发射参数之后,unbind(n)丢掉末尾 n 个发射参数- 同一 Callable 连两次返回
ERR_INVALID_PARAMETER并打印错误,先is_connected() CONNECT_ONE_SHOT触发一次后断开,CONNECT_DEFERRED推迟到帧末- 接收者释放时连接自动断开,lambda 捕获
self成员时也一样 - 只由外部发射的信号加
@warning_ignore("unused_signal") emit()不检查参数类型,接收方法参数类型不符时调用报错
<!-- check: gdonly -->extends Node
func _ready() -> void:
var stats: Dictionary = {"count": 0}
var bump := func() -> void:
stats["count"] += 1
bump.call()
bump.call()
print(stats["count"])- lambda 创建时按值捕获局部变量一次
- lambda 里
count += 1只改副本,触发confusable_capture_reassignment - 要回写就捕获 Array、Dictionary 或对象,改其内容
await 与协程
<!-- check: gdonly -->extends Node
signal answered(choice: int)
func open_door(door: Node3D) -> void:
await get_tree().create_timer(1.0).timeout
if not is_inside_tree() or not is_instance_valid(door):
return
door.hide()
func ask() -> int:
var choice: int = await answered
return choice| 情况 | 结果 |
调用协程不写 await | 跑到第一个 await 就返回,missing_await 默认关 |
| 信号带 1 个参数 | await 得到该值 |
| 信号带多个参数 | 得到 Array |
| 信号无参数 | 得到 null |
await 期间自己离开场景树 | get_tree() 打印错误并返回 null |
await 期间自己被 free() | 协程不再恢复,后面的清理不执行 |
await之后先检查is_inside_tree()和目标is_instance_valid()- 要清理的状态放
_exit_tree()或tree_exiting里复位 create_timer默认暂停时也走,要受暂停影响第二参数传false- 等一帧
await get_tree().process_frame,等物理帧physics_frame - 没有内置超时,用 Timer 的
timeout和业务信号谁先到谁处理
对象有效性
| 对象 | 规则 |
已 free() 的对象变量 | 不自动变 null,访问报 previously freed,用 is_instance_valid() 判断 |
queue_free() 后帧末前 | is_instance_valid() 仍为真,用 is_queued_for_deletion() |
RefCounted、Resource | 引用计数,不悬空,不用 free() |
| 长期持有可能被释放的节点 | 存 weakref(node),用时 get_ref() |
- 物理回调、信号回调、遍历子节点时释放用
queue_free() _init()里节点不在树内,get_node()失败
Callable 与延迟调用
<!-- check: gdonly -->extends Node
func _ready() -> void:
var child := Node.new()
add_child.call_deferred(child)
set_deferred(&"process_mode", Node.PROCESS_MODE_DISABLED)
var sorted: Array[int] = [3, 1, 2]
sorted.sort_custom(func(a: int, b: int) -> bool: return a > b)call_deferred在当前帧空闲阶段末尾执行,返回值永远是null- 物理回调里改碰撞形状、
Area2D.monitoring、CollisionShape2D.disabled用set_deferred - 线程里碰场景树只能
call_deferred - 方法引用写
_on_pressed,不写Callable(self, "_on_pressed") callable.is_valid()判断绑定对象是否还在
警告设置
项目设置 debug/gdscript/warnings/*,0 忽略、1 警告、2 错误,高级设置里可见。全表见 references/warnings.md。全类型化项目建议:
[debug]
gdscript/warnings/untyped_declaration=2
gdscript/warnings/missing_await=2
gdscript/warnings/narrowing_conversion=2
gdscript/warnings/int_as_enum_without_cast=2
gdscript/warnings/unassigned_variable=2- 单句忽略
@warning_ignore("unused_signal") - 区域忽略
@warning_ignore_start与@warning_ignore_restore directory_rules默认忽略res://addons
陷阱
match、静态成员、setter、super 的完整写法见 references/syntax.md。
| 现象 | 做法 |
5 / 2 得 2,触发 integer_division | 5 / 2.0 或 float(a) / b |
var b = a 后改 b,a 也变 | Array Dictionary 按引用传递,duplicate(),嵌套 duplicate(true) |
const 数组 append 报 Array is in read-only state | const 集合只读,改用 var |
父类 _init() _ready() 没执行 | 子类覆盖后要显式 super() |
| 声明初值没触发 setter | 初值不调 setter,类内其他赋值才调 |
unused_parameter | 参数名加下划线前缀 _delta |
narrowing_conversion | 浮点传整数参数时 int() roundi() floori() |
| 固定种子不生效 | 运行时已自动 randomize(),用 seed(),之后别再 randomize() |
| 遍历数组时增删元素跳项 | 遍历 arr.duplicate() 或倒序下标 |
call("do_it") 拼写错到运行时才暴露 | 用 Callable 引用与信号对象 |
native_method_override 报错 | 方法与引擎原生方法同名,改名 |
shadowed_variable | 局部变量与成员同名,改名 |
带 static var 的脚本持有大资源不释放 | 脚本不会卸载,手动清空 |
参考
- references/annotations.md:导出与其他注解全表
- references/syntax.md:match、静态成员、StringName、setter、super、可变参数与抽象类、断言与日志
- references/warnings.md:全部警告与默认值
- https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html
- https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html
- https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_exports.html
- https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/warning_system.html
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

