引言:从关键字到注解

Godot 4 将若干 GDScript 关键字替换为以 @ 为前缀的注解。这是让 GDScript 语法更简洁、更一致的整体改进的一部分。最重要的三项变化是:

  • export@export
  • onready@onready
  • tool@tool

注解放在其所修饰声明的上一行(或同一行)。Godot 4 还引入了许多 Godot 3 中不存在的新注解变体,如 @export_range@export_group@export_category。本指南将逐一讲解它们。

基本的 @export

@export 注解将变量暴露到 Godot 检查器中,让你无需编辑代码即可配置值。Godot 会根据变量类型自动选择合适的编辑器控件。

GDScript
@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" 之类的提示。

GDScript
@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 一起使用时,可以指定显式的数值。

GDScript
# 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 显示目录选择对话框。

GDScript
@export_file("*.tscn") var next_level: String
@export_dir var save_directory: String

过滤字符串使用通配符(glob)模式。多个过滤条件可用逗号分隔:"*.png,*.jpg"

@export_multiline 与 @export_placeholder

@export_multiline 为多行字符串提供大型文本区域(非常适合对话或描述文本)。@export_placeholder 在字段为空时显示提示文本。

GDScript
@export_multiline var description: String
@export_placeholder("Enter name...") var player_name: String

@export_group 与 @export_subgroup — 整理检查器属性

@export_group 在检查器中创建一个可折叠的分组标题。此后所有 @export 变量都归属于该分组,直到下一个分组或分类为止。@export_subgroup 则嵌套在当前分组之内。

GDScript
@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 在检查器中创建一个粗体的顶级分类标题。与分组不同,分类无法折叠,作为不相关属性集合之间的强视觉分隔。

GDScript
@export_category("Player Stats")
@export var level: int = 1
@export var experience: int = 0

用于节点引用的 @export

你可以导出一个 NodePath,让设计师从场景树中选取节点。在 Godot 4.2+ 中,你可以直接导出带类型的节点引用 — 无需 NodePath

GDScript
# 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 还为物理层和渲染层提供了内置的标志位导出。

GDScript
# 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() 中赋值)。当使用 $ 引用子节点时这是必需的,因为子节点在解析期尚不可用。

GDScript
# 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 之前。

GDScript
@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

在场景面板和「创建节点」对话框中,为脚本的节点类型设置自定义图标。

GDScript
@icon("res://icons/enemy.svg")
extends CharacterBody2D

@warning_ignore

抑制下一条语句的特定 GDScript 警告。当你有意遮蔽某个变量或存在未使用的参数时很有用。

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 能够在没有任何实例存在时将其从内存中卸载。这可以为仅临时使用的脚本降低内存占用。该脚本不得包含任何需要持久保留的静态变量或数据。

GDScript
@static_unload
extends RefCounted

# This script can be safely unloaded when not in use

静态类型最佳实践

静态类型提示虽然不是注解,但与其密切相关,并且在 Godot 4 中受到强烈推荐。它们能改进自动补全、支持编译期错误检查,还能提升性能。

GDScript
# 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
获取 Godot MCP Pro — $15