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 导出属性

In Godot, class members can be exported. This means their value gets saved along with the resource (such as the scene) they're attached to, and get transferred over when using RPCs. They will also be available for editing in the property editor. Exporting is done by using the @export annotation.

@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

Even if a script is not executed in the editor, exported properties can still be edited. However, getters and setters will only be used if the script is in 工具模式.

导出分组

可以使用 @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

备注

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

字符串用作文件路径

字符串为文件路径。见 @export_file

@export_file var f

字符串为目录路径。见 @export_dir

@export_dir var f

字符串为文件路径,提示中提供自定义筛选器。见 @export_file

@export_file("*.txt") var f

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

字符串为全局文件系统中 PNG 文件的路径。见 @export_global_file

@export_global_file("*.png") var tool_image

字符串为全局文件系统中目录的路径。见 @export_global_dir

@export_global_dir var tool_dir

多行文本注释会让编辑器使用大文本输入框来编辑多行文本。请查看 @export_multiline

@export_multiline var text

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

下列示例见 @export_range

允许 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

添加后缀与角度/弧度处理

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.

带缓动提示的浮点数

在编辑器里提供 'ease()' 函数的视觉呈现。请查看 @export_exp_easing

@export_exp_easing var transition_speed

颜色

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

@export var col: Color

颜色以红、绿、蓝值的形式给出(Alpha 值始终为 1)。见 @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

下拉列表就会限定到 AnimationNode 及其派生类。

导出位标记

@export_flags

Integers used as bit flags can store multiple true/false (boolean) values in one property. By using the @export_flags annotation, they can be set from the editor:

# 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的幂次方值才是有效的位标记选项。允许的最低值是1,因为0表示没有选中任何内容。你还可以添加一些其他标记的组合作为选项:

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

Export annotations are also provided for the physics, render, and navigation layers defined in the project settings:

@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

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

导出枚举

@export_enum

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

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

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

@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

@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

如果你需要比内置的 @export 注解更多的控制,可以使用 @export_custom。它允许定义任何属性提示、提示字符串和使用标志,语法与编辑器用于内置节点的语法类似。

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

@export_custom(PROPERTY_HINT_NONE, "suffix:m") var altitude: float

上述功能通常无法通过标准的 @export_range 语法实现,因为它需要定义范围。

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

警告

使用 @export_custom 时,GDScript 不会对语法进行任何验证。无效的语法可能会导致检查器中出现意外行为。

@export_tool_button

如果你需要创建一个可点击的检查器按钮,可以使用 @export_tool_button。这么写会将 Callable 类型的属性导出为可点击的按钮。按下按钮时,就会调用该可调用对象。

You can specify a custom icon name, which must match one of the icon file names from the editor/icons folder of the Godot source repository (case-sensitive). You can also browse the editor icons using the Godot editor icons website.

For example, if you wish to use Node2D.svg from that folder, you must specify "Node2D" as the second parameter of @export_tool_button. It is not currently possible to use custom icons from the project folder; only built-in editor icons can be used.

This exports a button with label "Hello" and icon "Callable" (which is the default if no icon is specified). 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 注解的修饰下,才能使上述方法在编辑器内运行。