Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

GDScript 导出属性

在 Godot 中,你可以导出类成员,其值会与其所附加的资源(例如场景)一起保存,也可以在属性编辑器中进行编辑。导出使用 @export 注解来实现。

@export var number: int = 5

在上面这个例子中,数值 5 会保存起来,并在属性编辑器中显示。

导出变量必须使用常量表达式来进行初始化,部分导出注解具有特殊类型,对变量类型不作要求(请参见下面的示例部分)。

导出成员变量的基本好处之一,便是让这些变量在编辑器中可见可改,这样一来,美术师和游戏设计师就可以修改这些会影响程序运行方式的值。为此,Godot 提供了一种特殊的导出语法。

备注

导出属性也可以用 C# 等其他语言完成。语法因语言而异。有关 C# 导出的信息见 C# 导出属性

基本用法

如果为导出变量赋予了常量值或常量表达式值,则可以对该变量的值进行类型推断,并使该变量在编辑器中可用。

@export var number = 5

如果导出变量没有默认值,那么你可以为该变量添加类型限定。

@export var number: int

可以导出资源和节点。

@export var resource: Resource
@export var node: Node

导出分组

可以使用 @export_group 注解来在检查器中对导出属性进行分组管理,在该注解后的每个导出变量均会被添加到该分组中。用一个新分组开头,或使用 @export_group("") 开头会结束之前的分组的作用范围。

@export_group("My Properties")
@export var number = 3

该注解的第二个参数仅囊括名称以该参数开头的导出变量。

导出项分组无法嵌套定义,需要用 @export_subgroup 来在一个大的导出项分组里定义一个小分组。

@export_subgroup("Extra Properties")
@export var string = ""
@export var flag = false

你还可以使用 @export_category 注解来更改主类别的名称,亦或在属性列表中创建其他类别。

@export_category("Main Category")
@export var number = 3
@export var string = ""

@export_category("Extra Category")
@export var flag = false

备注

属性列表是根据类的继承关系组织起来的,但新建导出项类别这个操作会破坏掉这种结构,故使用时需要格外小心,创建公共项目时更应如此。

字符串用作文件路径

String as a path to a file. See @export_file.

@export_file var f

String as a path to a directory. See @export_dir.

@export_dir var f

String as a path to a file, custom filter provided as hint. See again @export_file.

@export_file("*.txt") var f

也可以使用全局文件系统中的路径,仅工具模式下的脚本可以如此使用。

String as a path to a PNG file in the global filesystem. See @export_global_file.

@export_global_file("*.png") var tool_image

String as a path to a directory in the global filesystem. See @export_global_dir.

@export_global_dir var tool_dir

The multiline annotation tells the editor to show a large input field for editing over multiple lines. See @export_multiline.

@export_multiline var text

编辑器内限制值的输入范围

See @export_range for all of the following.

允许 0 到 20 之间的整数。

@export_range(0, 20) var i

允许 -10 到 20 之间的整数。

@export_range(-10, 20) var j

允许 -10 到 20 之间的数,调整步长为 0.2 。

@export_range(-10, 20, 0.2) var k: float

The limits can be made to affect only the slider if you add the hints "or_less" and/or "or_greater". If either these hints are used, it will be possible for the user to enter any value or drag the value with the mouse when not using the slider, even if outside the specified range.

@export_range(0, 100, 1, "or_less", "or_greater") var l: int

The "exp" hint can be used to make a value have an exponential slider instead of a linear slider. This means that when dragging the slider towards the right, changes will become progressively faster when dragging the mouse. This is useful to make editing values that can be either very small or very large easier, at the cost of being less intuitive.

@export_range(0, 100000, 0.01, "exp") var exponential: float

For values that are meant to represent an easing factor, use 带缓动提示的浮点数 instead.

The "hide_slider" hint can be used to hide the horizontal bar that appears below float properties, or the up/down arrows that appear besides int properties:

@export_range(0, 1000, 0.01, "hide_slider") var no_slider: float

Adding suffixes and handling degrees/radians

A suffix can also be defined to make the value more self-explanatory in the inspector. For example, to define a value that is meant to be configured as "meters" (m) by the user:

@export_range(0, 100, 1, "suffix:m") var m: int

For angles that are stored in radians but displayed as degrees to the user, use the "radians_as_degrees" hint:

@export_range(0, 360, 0.1, "radians_as_degrees") var angle: float

This performs automatic conversion when the value is displayed or modified in the inspector and also displays a degree (°) suffix. This approach is used by Godot's own rotation properties throughout the editor.

If the angle is stored in degrees instead, use the "degrees" hint to display the degree symbol while disabling the automatic degrees-to-radians conversion when the value is modified from the inspector.

带缓动提示的浮点数

Display a visual representation of the ease() function when editing. See @export_exp_easing.

@export_exp_easing var transition_speed

颜色

使用红、绿、蓝、Alpha 值指定普通颜色。

@export var col: Color

Color given as red-green-blue value (alpha will always be 1). See @export_color_no_alpha.

@export_color_no_alpha var col: Color

节点

从 Godot 4.0 开始,脚本中可以直接将节点作为属性导出,不必再使用 NodePath来辅助进行导出:

# Allows any node.
@export var node: Node

# Allows any node that inherits from BaseButton.
# Custom classes declared with `class_name` can also be used.
@export var some_button: BaseButton

如有需要,仍可以像 Godot 3.x 中那样导出 NodePath:

@export var node_path: NodePath
var node = get_node(node_path)

如果想要限制 NodePath 的类型,可以使用 @export_node_path 注解:

@export_node_path("Button", "TouchScreenButton") var some_button

资源

@export var resource: Resource

在检查器里,可以将资源文件从文件系统面板中拖放到导出变量所对应的槽位中。

不过,打开检查器的下拉列表可能会导致要创建的资源类列表非常之长。因此,如果在导出资源时指定了 Resource 的子类,例如:

@export var resource: AnimationNode

The drop-down menu will be limited to AnimationNode and all its derived classes.

必须注意:即使在在编辑器模式中未运行脚本,导出的属性仍可编辑。这一点可以与 使用工具模式的脚本 配合使用。

导出位标记

See @export_flags.

用作位标记的整数可以在一个属性中存储多个 true/ false (布尔)值。通过使用 @export_flags 注解来在编辑器中设置这些位标记:

# Set any of the given flags from the editor.
@export_flags("Fire", "Water", "Earth", "Wind") var spell_elements = 0

你必须为每个位标记提供一个字符串描述。在本例中,Fire 的值是 1,Water 的值是 2,Earth 的值是 4,Wind 的值是 8。通常情况下应相应地定义常量(例如 const ELEMENT_WIND = 8 等)。

可以用冒号将每个位标记及其值分隔开来:

@export_flags("Self:4", "Allies:8", "Foes:16") var spell_targets = 0

只有 2 的 n 次幂的整数才能作为位标记值使用,其最小值为 1(即 2 的 0 次幂),0 即表示无任何位标记选中。你还可以添加其他位标记,并将这些位标记进行组合:

@export_flags("Self:4", "Allies:8", "Self and Allies:12", "Foes:16")
var spell_targets = 0

也可以为项目设置中定义的物理层、渲染层和导航层提供导出提示:

@export_flags_2d_physics var layers_2d_physics
@export_flags_2d_render var layers_2d_render
@export_flags_2d_navigation var layers_2d_navigation
@export_flags_3d_physics var layers_3d_physics
@export_flags_3d_render var layers_3d_render
@export_flags_3d_navigation var layers_3d_navigation

使用位标记需要对位操作有一定的了解,若对此有疑问,请使用布尔变量代替位标记使用。

导出枚举

See @export_enum.

成员属性也可以通过将类型限定为一个枚举来导出,导出值为该枚举的枚举常量。编辑器会在相应位置创建一个列表,将枚举项按如“物体1”、“物体2”、“其他物体”的方式来进行排列显示。导出枚举的数值会按整数类型来存储。

enum NamedEnum {THING_1, THING_2, ANOTHER_THING = -1}
@export var x: NamedEnum

也可以使用 @export_enum 注解来将整数和字符串属性限制为特定的值列表。编辑器将在检查器中创建一个小工具,将以下枚举为:战士、魔术师、小偷。该值将被存储为整数,对应于所选选项的索引(即 01、或 2)。

@export_enum("Warrior", "Magician", "Thief") var character_class: int

可以用冒号将每个位标记及其值分隔开来:

@export_enum("Slow:30", "Average:60", "Very Fast:200") var character_speed: int

如果变量类型是字符串,则枚举字符串本身就是该变量的可选数值。

@export_enum("Rebecca", "Mary", "Leah") var character_name: String

若要设置其初始值,须显式声明其值:

@export_enum("Rebecca", "Mary", "Leah") var character_name: String = "Rebecca"

导出数组

导出的数组可以赋予初始值,但其初始值必须是常量表达式。

如果导出的数组指定了继承自 Resource 类型的对象,则可以从文件系统面板中一次性拖放多个文件来到检查器中来设置数组值。

默认值必须是常量表达式。

@export var a = [1, 2, 3]

导出数组也可以指定元素类型(使用之前提到的提示即可)。

@export var ints: Array[int] = [1, 2, 3]

# Nested typed arrays such as `Array[Array[float]]` are not supported yet.
@export var two_dimensional: Array[Array] = [[1.0, 2.0], [3.0, 4.0]]

也可以不声明初始值,这样的话,数组的初始值就默认为 null

@export var b: Array
@export var scenes: Array[PackedScene]

如果导出的数组指定了从 Resource 继承的类型,则可以一次性从文件系统面板中拖放多个文件到检查器中来设置该数组的值。

@export var textures: Array[Texture] = []
@export var scenes: Array[PackedScene] = []

压缩数组也可以使用导出,但需要构造对应的空压缩数组去赋值:

@export var vector3s = PackedVector3Array()
@export var strings = PackedStringArray()

属性提示可以用来导出字符串作为路径:

@export_range(-360, 360, 0.001, "degrees") var laser_angles: Array[float] = []
@export_file("*.json") var skill_trees: Array[String] = []
@export_color_no_alpha var hair_colors = PackedColorArray()
@export_enum("Espresso", "Mocha", "Latte", "Capuccino") var barista_suggestions: Array[String] = []

@export_storage

See @export_storage.

导出属性在默认情况下会产生以下两种效果:

  1. 将属性存到场景/资源文件当中(即 PROPERTY_USAGE_STORAGE 位标志的作用);

  2. 将字段加到检查器当中(即 PROPERTY_USAGE_EDITOR 位标志的作用)。

然而有时你会想让某个属性能够序列化,不让它显示在编辑器当中,以防误修改其值,同时避免检查器窗口杂乱无章。

可以使用 @export_storage 注解来实现上述效果,该注解在 @tool 脚本中十分有用。而且,与非导出属性不同的是,如果调用 Resource.duplicate()Node.duplicate() 方法,会复制该属性的值。

var a # Not stored in the file, not displayed in the editor.
@export_storage var b # Stored in the file, not displayed in the editor.
@export var c: int # Stored in the file, displayed in the editor.

@export_custom

If you need more control than what's exposed with the built-in @export annotations, you can use @export_custom instead. This allows defining any property hint, hint string and usage flags, with a syntax similar to the one used by the editor for built-in nodes.

For example, this exposes the altitude property with no range limits but a m (meter) suffix defined:

@export_custom(PROPERTY_HINT_NONE, "altitude:m") var altitude: Vector3

The above is normally not feasible with the standard @export_range syntax, since it requires defining a range.

See the class reference for a list of parameters and their allowed values.

警告

When using @export_custom, GDScript does not perform any validation on the syntax. Invalid syntax may have unexpected behavior in the inspector.

@export_tool_button

If you need to create a clickable inspector button, you can use @export_tool_button. This exports a Callable property as a clickable button. When the button is pressed, the callable is called.

Export a button with label "Hello" and icon "Callable". When you press it, it will print "Hello world!".

@tool
extends Node

@export_tool_button("Hello", "Callable") var hello_action = hello

func hello():
    print("Hello world!")

从工具脚本中设置导出变量

工具模式 下的脚本中的一个导出变量的值改变时,该值在检查器中不会自动更新。更新的方法是在设置该导出变量的值之后调用 notify_property_list_changed()

高级导出

为了避免非必要的复杂设计,并非所有类型的导出都在语言层面上提供。下面将说明一些能用底层 API 实现的,且较为常见的导出方法。

在进一步阅读前,你需要熟悉属性的处理方式,以及如何通过 _set()_get()_get_property_list() 等方法进行定制的这些属性。详见 从对象访问数据或逻辑

参见

要在 C++ 中用上述方法绑定属性,请参阅 使用 _set/_get/_get_property_list 绑定属性

警告

脚本必须在 @tool 注解的修饰下,才能使上述方法在编辑器内运行。