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
备注
属性列表是根据类的继承关系组织起来的,但新建导出项类别这个操作会破坏掉这种结构,故使用时需要格外小心,创建公共项目时更应如此。
字符串用作文件路径
字符串可以用作文件路径。
@export_file var f
字符串也可以用作文件目录路径。
@export_dir var f
字符串在用作是文件路径时,可以在提示项中提供自定义过滤器。
@export_file("*.txt") var f
也可以使用全局文件系统中的路径,仅工具模式下的脚本可以如此使用。
字符串还可以用作全局文件系统中某个 PNG 文件的路径。
@export_global_file("*.png") var tool_image
字符串也能用作全局文件系统中某个目录的路径。
@export_global_dir var tool_dir
多行文本注释会让编辑器使用大文本输入框来输入文本,而非那种小小的单行输入框。
@export_multiline var text
编辑器内限制值的输入范围
允许 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
可以添加 “or_greater” 及/或 “or_less” 提示来突破(编辑器滑条的)范围限制。
@export_range(0, 100, 1, "or_greater", "or_less")
带缓动提示的浮点数
在编辑器里提供 ‘ease()’ 函数的视觉呈现。
@export_exp_easing var transition_speed
颜色
使用红、绿、蓝、Alpha 值指定普通颜色。
@export var col: Color
使用红、绿、蓝值指定颜色(此时Alpha 始终为 1)。
@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 类资源及其子类资源上。
必须注意:即使在在编辑器模式中未运行脚本,导出的属性仍可编辑。这一点可以与 使用工具模式的脚本 配合使用。
导出位标记
用作位标记的整数可以在一个属性中存储多个 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
使用位标记需要对位操作有一定的了解,若对此有疑问,请使用布尔变量代替位标记使用。
导出枚举
成员属性也可以通过将类型限定为一个枚举来导出,导出值为该枚举的枚举常量。编辑器会在相应位置创建一个列表,将枚举项按如“物体1”、“物体2”、“其他物体”的方式来进行排列显示。导出枚举的数值会按整数类型来存储。
enum NamedEnum {THING_1, THING_2, ANOTHER_THING = -1}
@export var x: NamedEnum
也可以使用 @export_enum 注解来将整数和字符串属性限制为特定的值列表。编辑器将在检查器中创建一个小工具,将以下枚举为:战士、魔术师、小偷。该值将被存储为整数,对应于所选选项的索引(即 0
、1
、或 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]
导出数组也可以指定元素类型(类型名 Array 后接 [元素类型名] 即可)。
@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, "radians") 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
导出属性在默认情况下会产生以下两种效果:
将属性存到场景/资源文件当中(即 :ref:`PROPERTY_USAGE_STORAGE <class_@GlobalScope_constant_PROPERTY_USAGE_STORAGE>`位标志的作用);
将字段加到检查器当中(即 :ref:`PROPERTY_USAGE_EDITOR <class_@GlobalScope_constant_PROPERTY_USAGE_EDITOR>`位标志的作用)。
然而有时你会想让某个属性能够序列化,不让它显示在编辑器当中,以防误修改其值,同时避免检查器窗口杂乱无章。
可以使用 @export_storage 脚本中十分有用。同时,与非导出属性不同的是,如果调用 Resource.duplicate() 或 :ref:`Node.duplicate() <class_Node_method_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.
从工具脚本中设置导出变量
当 工具模式 下的脚本中的一个导出变量的值改变时,该值在检查器中不会自动更新。要更新它,请在设置该导出变量的值之后调用 notify_property_list_changed()。
高级导出
为了避免非必要的复杂设计,并非所有类型的导出都在语言层面上提供。下面将说明一些能用底层 API 实现的,且较为常见的导出方法。
在进一步阅读前,你需要熟悉属性的处理方式,以及如何通过 _set()、 _get()、 _get_property_list() 等方法进行定制的这些属性。详情可参阅 从对象访问数据或逻辑。
参见
要在 C++ 中用上述方法绑定属性,请参阅 使用 _set/_get/_get_property_list 绑定属性。
警告
脚本必须在 @tool
注解的修饰下,才能使上述方法在编辑器内运行。