引言:从关键字到注解
Godot 4 将若干 GDScript 关键字替换为以 @ 为前缀的注解。这是让 GDScript 语法更简洁、更一致的整体改进的一部分。最重要的三项变化是:
export→@exportonready→@onreadytool→@tool
注解放在其所修饰声明的上一行(或同一行)。Godot 4 还引入了许多 Godot 3 中不存在的新注解变体,如 @export_range、@export_group 和 @export_category。本指南将逐一讲解它们。
基本的 @export
@export 注解将变量暴露到 Godot 检查器中,让你无需编辑代码即可配置值。Godot 会根据变量类型自动选择合适的编辑器控件。
@export var speed: float = 300.0
@export var player_name: String = "Player"
@export var health: int = 100
@export var color: Color = Color.WHITE
@export var texture: Texture2D
@export var scene: PackedScene
提示: 始终为导出变量添加类型注解。这样能确保检查器显示正确的控件(例如 Color 显示拾色器,Texture2D 显示资源槽)。
@export_range — 数值滑块
@export_range 将数值限制在最小值与最大值之间,并在检查器中显示滑块。你还可以指定步长以及 "or_greater"、"or_less" 之类的提示。
@export_range(0, 100) var health: int = 100
@export_range(0.0, 1.0, 0.01) var volume: float = 0.8
@export_range(0, 1000, 1, "or_greater") var damage: int = 10
"or_greater" 提示允许在保持滑块范围聚焦的同时输入超过最大值的值。同样,"or_less" 允许输入低于最小值的值。
@export_enum — 下拉菜单
@export_enum 在检查器中创建一个下拉框。与 String 一起使用时,保存所选选项的名称;与 int 一起使用时,可以指定显式的数值。
# Stores the string name: "Warrior", "Mage", or "Rogue"
@export_enum("Warrior", "Mage", "Rogue") var character_class: String
# Stores the integer value: 0, 1, or 2
@export_enum("Easy:0", "Normal:1", "Hard:2") var difficulty: int = 1
@export_file 与 @export_dir — 文件/目录路径
@export_file 在检查器中显示文件对话框,可以按文件扩展名过滤。@export_dir 显示目录选择对话框。
@export_file("*.tscn") var next_level: String
@export_dir var save_directory: String
过滤字符串使用通配符(glob)模式。多个过滤条件可用逗号分隔:"*.png,*.jpg"。
@export_multiline 与 @export_placeholder
@export_multiline 为多行字符串提供大型文本区域(非常适合对话或描述文本)。@export_placeholder 在字段为空时显示提示文本。
@export_multiline var description: String
@export_placeholder("Enter name...") var player_name: String
@export_group 与 @export_subgroup — 整理检查器属性
@export_group 在检查器中创建一个可折叠的分组标题。此后所有 @export 变量都归属于该分组,直到下一个分组或分类为止。@export_subgroup 则嵌套在当前分组之内。
@export_group("Movement")
@export var speed: float = 300.0
@export var jump_force: float = 400.0
@export_group("Combat")
@export var attack_damage: int = 10
@export var defense: int = 5
@export_subgroup("Ranged")
@export var projectile_speed: float = 500.0
分组和子分组纯粹用于整理 — 它们不影响代码中对变量的访问,只影响属性在检查器中的显示方式。
@export_category — 粗体分类标题
@export_category 在检查器中创建一个粗体的顶级分类标题。与分组不同,分类无法折叠,作为不相关属性集合之间的强视觉分隔。
@export_category("Player Stats")
@export var level: int = 1
@export var experience: int = 0
用于节点引用的 @export
你可以导出一个 NodePath,让设计师从场景树中选取节点。在 Godot 4.2+ 中,你可以直接导出带类型的节点引用 — 无需 NodePath。
# Classic NodePath export
@export var target_path: NodePath
# Godot 4.2+: typed node export (direct reference, no NodePath needed)
@export var sprite: Sprite2D
@export var collision: CollisionShape2D
带类型的节点导出是现代 Godot 4 中推荐的方式。检查器会显示按指定类型过滤的节点选择器,并且你在脚本编辑器中能获得完整的自动补全。
@export_flags — 位掩码复选框
@export_flags 创建一组复选框,每个选项对应整数中的一个位。Godot 还为物理层和渲染层提供了内置的标志位导出。
# Custom flags: Fire=1, Water=2, Earth=4, Wind=8
@export_flags("Fire", "Water", "Earth", "Wind") var elements: int
# Built-in physics layer flags
@export_flags_2d_physics var collision_layers: int
@export_flags_2d_render var render_layers: int
@export_flags_3d_physics var collision_layers_3d: int
@onready — 延迟初始化
@onready 将变量初始化推迟到节点进入场景树时执行(等价于在 _ready() 中赋值)。当使用 $ 引用子节点时这是必需的,因为子节点在解析期尚不可用。
# Godot 3 (old syntax):
# onready var sprite = $Sprite2D
# Godot 4:
@onready var sprite: Sprite2D = $Sprite2D
@onready var anim: AnimationPlayer = $AnimationPlayer
@onready var label: Label = $UI/ScoreLabel
最佳实践: 始终为 @onready 变量标注类型。这样可以启用自动补全,并在解析期而非运行期捕获类型错误。
@tool — 在编辑器中运行脚本
@tool 让脚本在 Godot 编辑器内运行(而不仅仅在运行期)。这对于创建自定义预览、Gizmo 以及实时更新的属性非常强大。将它放在脚本最顶部、extends 之前。
@tool
extends Node2D
@export var radius: float = 100.0:
set(value):
radius = value
queue_redraw() # Redraw in editor when value changes
func _draw() -> void:
draw_circle(Vector2.ZERO, radius, Color.WHITE)
警告: 使用 @tool 脚本时要小心。_process() 和 _physics_process() 中的代码会在编辑器内运行。请用 Engine.is_editor_hint() 来保护仅用于游戏的逻辑。
其他注解
@icon
在场景面板和「创建节点」对话框中,为脚本的节点类型设置自定义图标。
@icon("res://icons/enemy.svg")
extends CharacterBody2D
@warning_ignore
抑制下一条语句的特定 GDScript 警告。当你有意遮蔽某个变量或存在未使用的参数时很有用。
@warning_ignore("unused_parameter")
func _on_body_entered(body: Node2D) -> void:
queue_free()
@warning_ignore("shadowed_variable")
var size: int = 10
@static_unload
标记脚本,使 Godot 能够在没有任何实例存在时将其从内存中卸载。这可以为仅临时使用的脚本降低内存占用。该脚本不得包含任何需要持久保留的静态变量或数据。
@static_unload
extends RefCounted
# This script can be safely unloaded when not in use
静态类型最佳实践
静态类型提示虽然不是注解,但与其密切相关,并且在 Godot 4 中受到强烈推荐。它们能改进自动补全、支持编译期错误检查,还能提升性能。
# Variable type annotations
var speed: float = 300.0
var player: CharacterBody2D = null
var items: Array[String] = []
var scores: Dictionary = {}
# Function return types and parameter types
func get_damage() -> int:
return attack - defense
func apply_force(direction: Vector2, strength: float) -> void:
velocity += direction * strength
# Type inference with :=
var pos := Vector2(100, 200) # Inferred as Vector2
注意: 在遍历无类型数组的 for 循环中使用 := 时要小心。改用显式类型注解:for item: String in array。
迁移速查表:Godot 3 到 4
将 Godot 3 的导出语法转换为 Godot 4 注解的快速参考:
| Godot 3 | Godot 4 | 说明 |
|---|---|---|
export var x |
@export var x |
基本导出 |
export(int, 0, 100) var hp |
@export_range(0, 100) var hp: int |
带类型提示的范围 |
export(String, "A", "B") var x |
@export_enum("A", "B") var x: String |
枚举下拉框 |
export(String, FILE) var path |
@export_file var path: String |
文件选择器 |
export(String, MULTILINE) var text |
@export_multiline var text: String |
多行文本区域 |
export(int, FLAGS, ...) var f |
@export_flags(...) var f: int |
位掩码标志位 |
onready var x = $Node |
@onready var x: Type = $Node |
延迟初始化 |
tool |
@tool |
编辑器执行 |
| 无 | @export_group("...") |
Godot 4 新增 |
| 无 | @export_category("...") |
Godot 4 新增 |
| 无 | @export_subgroup("...") |
Godot 4 新增 |
Godot MCP Pro 理解所有 @export 注解
Godot MCP Pro 可以创建带有正确类型导出的脚本、读取和修改现有的导出注解,并检查场景中任意节点的导出属性 — 全部通过 AI 完成。
- create_script
- edit_script
- read_script
- get_node_properties
- get_scene_exports
- update_property