GDScript使用静态类型并开启严格的类型检查
为 Godot 项目配置严格的 GDScript 静态类型检查
Godot 4.2+ 的 GDScript 警告系统允许你在项目级别精细控制类型安全检查的严格程度。 本文介绍如何一键开启最严格的类型检查,同时跳过第三方插件,避免误报。
背景
GDScript 从 Godot 4.0 起支持完整的静态类型系统。默认情况下,许多类型相关的警告只是提示级别(warning),不会阻止你运行游戏。对于追求代码质量的项目,可以将其提升为错误级别,让编辑器在编译阶段就拦截类型问题。
核心思路很简单:每一项警告都可以独立设置为三个等级之一:
| 等级值 | 含义 | 效果 |
|---|---|---|
0 |
IGNORE | 完全忽略,不显示 |
1 |
WARN | 黄色警告,不阻止运行 |
2 |
ERROR | 红色错误,阻止编译 |
快速配置
在项目根目录的 project.godot 中添加(或合并)以下内容:
[debug]
; 启用警告系统
gdscript/warnings/enable=true
; 跳过 addons/ 目录(第三方插件不检查)
gdscript/warnings/exclude_addons=true
; ====== 类型安全 — ERROR ======
gdscript/warnings/untyped_declaration=2
gdscript/warnings/unsafe_property_access=2
gdscript/warnings/unsafe_method_access=2
gdscript/warnings/unsafe_cast=2
gdscript/warnings/unsafe_call_argument=2
gdscript/warnings/incompatible_ternary=2
gdscript/warnings/narrowing_conversion=2
gdscript/warnings/int_as_enum_without_cast=2
gdscript/warnings/int_as_enum_without_match=2
gdscript/warnings/confusable_identifier=2
gdscript/warnings/redundant_static_unreachable=2
; ====== 未使用 / 影子变量 — WARN ======
gdscript/warnings/unused_variable=1
gdscript/warnings/unused_parameter=1
gdscript/warnings/unused_signal=1
gdscript/warnings/unused_local_constant=1
gdscript/warnings/unused_private_class_variable=1
gdscript/warnings/shadowed_variable=1
gdscript/warnings/shadowed_variable_base_class=1
gdscript/warnings/shadowed_global_identifier=1
; ====== 代码质量 — WARN ======
gdscript/warnings/unreachable_code=1
gdscript/warnings/unreachable_pattern=1
gdscript/warnings/standalone_expression=1
gdscript/warnings/standalone_ternary=1
gdscript/warnings/deprecated_keyword=1
gdscript/warnings/confusable_local_declaration=1
gdscript/warnings/empty_assignment=1
gdscript/warnings/return_value_discarded=1
; ====== 推断风格 — WARN ======
gdscript/warnings/inferred_declaration=1
也可以在 Godot 编辑器中操作:Project → Project Settings → 勾选 Advanced Settings → Debug → GDScript → Warnings。
完整警告项参考
以下列出 Godot 4.2+ 所有可配置的 GDScript 警告项,附中英文名称和推荐等级。
🔴 类型安全 — 设为 ERROR(2)
这些警告直接关系到运行时类型安全,建议始终设为 2(错误)。
| 设置键 | 英文名称 | 中文名称 | 触发场景 |
|---|---|---|---|
untyped_declaration |
Untyped Declaration | 未类型化声明 | 变量、参数或返回值缺少类型注解 |
unsafe_property_access |
Unsafe Property Access | 不安全的属性访问 | 在 Variant 或动态类型上访问属性 |
unsafe_method_access |
Unsafe Method Access | 不安全的方法访问 | 在 Variant 或动态类型上调用方法 |
unsafe_cast |
Unsafe Cast | 不安全的类型转换 | 无法验证的 as 转换 |
unsafe_call_argument |
Unsafe Call Argument | 不安全的调用参数 | 传递了类型不匹配的参数 |
incompatible_ternary |
Incompatible Ternary | 不兼容的三元运算 | 三元运算符的两个分支类型不同 |
narrowing_conversion |
Narrowing Conversion | 窄化转换 | 隐式将 float 转为 int 等精度损失转换 |
int_as_enum_without_cast |
Int as Enum Without Cast | 整数直接当枚举(无转换) | 将整数赋值给枚举类型但未显式转换 |
int_as_enum_without_match |
Int as Enum Without Match | 整数枚举无匹配 | 整数值不对应任何枚举成员 |
confusable_identifier |
Confusable Identifier | 易混淆标识符 | 变量名与内置类型/类名极度相似 |
redundant_static_unreachable |
Redundant Static Unreachable | 冗余的静态不可达代码 |
@static_unload 中不可达的代码 |
🟡 未使用 / 影子变量 — 设为 WARN(1)
这些是代码整洁性警告,提示但不阻止运行。
| 设置键 | 英文名称 | 中文名称 | 触发场景 |
|---|---|---|---|
unused_variable |
Unused Variable | 未使用的变量 | 声明了变量但从未读取 |
unused_parameter |
Unused Parameter | 未使用的参数 | 函数参数声明了但函数体内未使用 |
unused_signal |
Unused Signal | 未使用的信号 | 声明了信号但从未 connect 或 emit |
unused_local_constant |
Unused Local Constant | 未使用的局部常量 | 声明了常量但从未引用 |
unused_private_class_variable |
Unused Private Class Variable | 未使用的私有类变量 |
_ 前缀的类变量未被使用 |
shadowed_variable |
Shadowed Variable | 影子变量 | 内层作用域声明了与外层同名的变量 |
shadowed_variable_base_class |
Shadowed Variable Base Class | 影子基类变量 | 子类变量遮蔽了基类同名变量 |
shadowed_global_identifier |
Shadowed Global Identifier | 影子全局标识符 | 局部变量遮蔽了全局类名/常量 |
🟡 代码质量 — 设为 WARN(1)
| 设置键 | 英文名称 | 中文名称 | 触发场景 |
|---|---|---|---|
unreachable_code |
Unreachable Code | 不可达代码 |
return/break 之后还有代码 |
unreachable_pattern |
Unreachable Pattern | 不可达的 match 分支 |
match 中永远无法匹配到的 pattern |
standalone_expression |
Standalone Expression | 独立表达式 | 仅计算但不使用结果的语句 |
standalone_ternary |
Standalone Ternary | 独立的三元运算 | 三元表达式作为独立语句使用 |
deprecated_keyword |
Deprecated Keyword | 已弃用的关键字 | 使用了旧版 GDScript 关键字 |
confusable_local_declaration |
Confusable Local Declaration | 易混淆的局部声明 | 局部变量名与外部作用域极度相似 |
empty_assignment |
Empty Assignment | 空赋值 | 将变量赋值为自身(无意义操作) |
return_value_discarded |
Return Value Discarded | 返回值被丢弃 | 调用了有返回值的函数但未使用返回值 |
🟡 推断风格 — 设为 WARN(1)
| 设置键 | 英文名称 | 中文名称 | 触发场景 |
|---|---|---|---|
inferred_declaration |
Inferred Declaration | 推断类型声明 | 使用 := 推断而非显式 : Type 声明 |
⚙️ Godot 4.2 默认已为 ERROR 的警告
以下警告在 Godot 4.2 中默认就是错误级别,无需额外配置:
| 设置键 | 英文名称 | 中文名称 | 触发场景 |
|---|---|---|---|
inference_on_variant |
Inference on Variant | Variant 上的类型推断 | 对 Variant 使用 := 推断 |
native_method_override |
Native Method Override | 原生方法覆盖 | 覆盖了引擎内置的虚方法 |
get_node_default_without_onready |
get_node Without @onready | get_node 缺少 @onready | 在 _ready 外使用 get_node 但未加 @onready |
onready_with_export |
@onready With @export | @onready 与 @export 共用 | 同时使用 @onready 和 @export |
跳过插件检查
gdscript/warnings/exclude_addons=true
这一行是关键。Godot 生态中有大量社区插件(在 addons/ 目录下),它们的代码质量参差不齐。如果你开启了严格检查,这些插件的警告会淹没你自己代码的警告。
设置 exclude_addons=true 后,编辑器只会检查 addons/ 目录之外的 .gd 文件,插件代码完全跳过。
推荐策略
根据项目阶段选择不同的严格程度:
🔥 新项目 / 追求高质量
直接使用本文开头的完整配置。从第一天起就强制类型安全,避免技术债积累。
⚡ 现有项目迁移
分两步走:
-
第一步:将所有类型安全警告设为
WARN(1),先修复代码 -
第二步:确认无警告后,再升级为
ERROR(2)
🛡️ 游戏原型 / Game Jam
只开启类型安全相关的 ERROR 项,其余保持默认即可。在有限时间内不必追求零警告。
配置原则总结
类型安全问题 → ERROR(必须修)
代码整洁问题 → WARN(应该修)
第三方插件代码 → 跳过(exclude_addons=true)
这三条规则覆盖了 90% 的场景。如果你需要更细粒度的控制,参考上面的完整表格逐项调整。