GDScript 导出

导出简介

在 Godot 中可以导出类成员。这意味着它们的值会与它们所附加的资源(例如场景)一起保存。它们也可以在属性编辑器中进行编辑。导出使用关键字 export 来完成:

  1. extends Button
  2. export var number = 5 # Value will be saved and visible in the property editor.

导出的变量必须使用常量表达式初始化,或者用 export 关键字参数的形式提供导出提示(请参见下面的示例部分)。

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

备注

C# 等其他语言也可以进行属性的导出。不同的语言有不同的语法。

示例

  1. # If the exported value assigns a constant or constant expression,
  2. # the type will be inferred and used in the editor.
  3. export var number = 5
  4. # Export can take a basic data type as an argument, which will be
  5. # used in the editor.
  6. export(int) var number
  7. # Export can also take a resource type to use as a hint.
  8. export(Texture) var character_face
  9. export(PackedScene) var scene_file
  10. # There are many resource types that can be used this way, try e.g.
  11. # the following to list them:
  12. export(Resource) var resource
  13. # Integers and strings hint enumerated values.
  14. # Editor will enumerate as 0, 1 and 2.
  15. export(int, "Warrior", "Magician", "Thief") var character_class
  16. # Editor will enumerate with string names.
  17. export(String, "Rebecca", "Mary", "Leah") var character_name
  18. # Named enum values
  19. # Editor will enumerate as THING_1, THING_2, ANOTHER_THING.
  20. enum NamedEnum {THING_1, THING_2, ANOTHER_THING = -1}
  21. export(NamedEnum) var x
  22. # Strings as paths
  23. # String is a path to a file.
  24. export(String, FILE) var f
  25. # String is a path to a directory.
  26. export(String, DIR) var f
  27. # String is a path to a file, custom filter provided as hint.
  28. export(String, FILE, "*.txt") var f
  29. # Using paths in the global filesystem is also possible,
  30. # but only in scripts in "tool" mode.
  31. # String is a path to a PNG file in the global filesystem.
  32. export(String, FILE, GLOBAL, "*.png") var tool_image
  33. # String is a path to a directory in the global filesystem.
  34. export(String, DIR, GLOBAL) var tool_dir
  35. # The MULTILINE setting tells the editor to show a large input
  36. # field for editing over multiple lines.
  37. export(String, MULTILINE) var text
  38. # Limiting editor input ranges
  39. # Allow integer values from 0 to 20.
  40. export(int, 20) var i
  41. # Allow integer values from -10 to 20.
  42. export(int, -10, 20) var j
  43. # Allow floats from -10 to 20 and snap the value to multiples of 0.2.
  44. export(float, -10, 20, 0.2) var k
  45. # Allow values 'y = exp(x)' where 'y' varies between 100 and 1000
  46. # while snapping to steps of 20. The editor will present a
  47. # slider for easily editing the value.
  48. export(float, EXP, 100, 1000, 20) var l
  49. # Floats with easing hint
  50. # Display a visual representation of the 'ease()' function
  51. # when editing.
  52. export(float, EASE) var transition_speed
  53. # Colors
  54. # Color given as red-green-blue value (alpha will always be 1).
  55. export(Color, RGB) var col
  56. # Color given as red-green-blue-alpha value.
  57. export(Color, RGBA) var col
  58. # Nodes
  59. # Another node in the scene can be exported as a NodePath.
  60. export(NodePath) var node_path
  61. # Do take note that the node itself isn't being exported -
  62. # there is one more step to call the true node:
  63. onready var node = get_node(node_path)
  64. # Resources
  65. export(Resource) var resource
  66. # In the Inspector, you can then drag and drop a resource file
  67. # from the FileSystem dock into the variable slot.
  68. # Opening the inspector dropdown may result in an
  69. # extremely long list of possible classes to create, however.
  70. # Therefore, if you specify an extension of Resource such as:
  71. export(AnimationNode) var resource
  72. # The drop-down menu will be limited to AnimationNode and all
  73. # its inherited classes.

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

导出位标志

用作位标志的整数可以在一个属性中存储多个 true/ false(布尔)值。通过使用导出提示 int, FLAGS, ...,可以在编辑器中设置它们:

  1. # Set any of the given flags from the editor.
  2. export(int, FLAGS, "Fire", "Water", "Earth", "Wind") var spell_elements = 0

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

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

  1. export(int, LAYERS_2D_PHYSICS) var layers_2d_physics
  2. export(int, LAYERS_2D_RENDER) var layers_2d_render
  3. export(int, LAYERS_3D_PHYSICS) var layers_3d_physics
  4. export(int, LAYERS_3D_RENDER) var layers_3d_render

使用位标志需要对位操作有一定的了解. 如果有疑问, 请使用布尔变量代替.

导出数组

导出的数组可以具有初始化器, 但是它们必须是常量表达式.

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

  1. # Default value must be a constant expression.
  2. export var a = [1, 2, 3]
  3. # Exported arrays can specify type (using the same hints as before).
  4. export(Array, int) var ints = [1, 2, 3]
  5. export(Array, int, "Red", "Green", "Blue") var enums = [2, 1, 0]
  6. export(Array, Array, float) var two_dimensional = [[1.0, 2.0], [3.0, 4.0]]
  7. # You can omit the default value, but then it would be null if not assigned.
  8. export(Array) var b
  9. export(Array, PackedScene) var scenes
  10. # Arrays with specified types which inherit from resource can be set by
  11. # drag-and-dropping multiple files from the FileSystem dock.
  12. export(Array, Texture) var textures
  13. export(Array, PackedScene) var scenes
  14. # Typed arrays also work, only initialized empty:
  15. export var vector3s = PoolVector3Array()
  16. export var strings = PoolStringArray()
  17. # Default value can include run-time values, but can't
  18. # be exported.
  19. var c = [a, 2, 3]

从工具脚本设置导出变量

工具模式 下的脚本中更改一个导出变量的值时,检查器中对应的值不会自动更新。要更新它,请在设置导出变量的值之后,调用 property_list_changed_notify()

高级导出

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

在进一步阅读前,你需要熟悉属性的运作方式以及它们是如何通过 _set()_get()_get_property_list() 方法进行定制的。详情可参阅 从对象访问数据或逻辑

参见

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

警告

脚本必须在 tool 模式运行,上述方法才能在编辑器内运行。

属性

为了更好地理解后续章节,你应该理解如何使用高级导出来制作属性。

  1. func _get_property_list():
  2. var properties = []
  3. # Same as "export(int) var my_property"
  4. properties.append({
  5. name = "my_property",
  6. type = TYPE_INT
  7. })
  8. return properties
  • 检查器会调用 _get_property_list() 函数。你可以对它进行覆盖,进行高级导出。要让这个函数正常工作,你必须返回一个包含属性内容的 Array

  • name 是该属性的名称

  • type 是该属性的类型,使用 Variant.Type

备注

浮点数类型 floatVariant.Type 枚举中叫作实数(TYPE_REAL)。

将变量与属性关联

要将变量与属性关联起来(让属性的值可以在脚本中使用),你需要创建一个与该属性同名的变量,否则就需要覆盖 _set()_get() 方法。将变量与属性关联后,你还可以给它设置默认状态。

  1. # This variable is determined by the function below.
  2. # This variable acts just like a regular gdscript export.
  3. var my_property = 5
  4. func _get_property_list():
  5. var properties = []
  6. # Same as "export(int) var my_property"
  7. properties.append({
  8. name = "my_property",
  9. type = TYPE_INT
  10. })
  11. return properties

Adding default values for properties

To define default values for advanced exports, you need to override the property_can_revert() and property_get_revert() methods.

  • The property_can_revert() method takes the name of a property and must return true if the property can be reverted. This will enable the Revert button next to the property in the inspector.

  • The property_get_revert() method takes the name of a property and must return the default value for that property.

  1. func _get_property_list():
  2. var properties = []
  3. properties.append({
  4. name = "my_property",
  5. type = TYPE_INT
  6. })
  7. return properties
  8. func property_can_revert(property):
  9. if property == "my_property":
  10. return true
  11. return false
  12. func property_get_revert(property):
  13. if property == "my_property":
  14. return 5

添加脚本分类

为了在视觉上更好区分各个属性,可以将特殊的脚本分类作为分隔线嵌入检查器。Script Variables 就是一种内建分类。

  1. func _get_property_list():
  2. var properties = []
  3. properties.append({
  4. name = "Debug",
  5. type = TYPE_NIL,
  6. usage = PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_SCRIPT_VARIABLE
  7. })
  8. # Example of adding a property to the script category
  9. properties.append({
  10. name = "Logging_Enabled",
  11. type = TYPE_BOOL
  12. })
  13. return properties
  • name 是要加入检查器中的分类的名字;

  • 定义分类后,添加的所有属性都会成为该分类的一部分。

  • PROPERTY_USAGE_CATEGORY 表明了该属性应被视为一个脚本分类,因此可以忽略 TYPE_NIL 这个类型,因为它其实并没有被脚本逻辑所处理。不过你还是必须在这儿定义它。

对属性进行分组

名称类似的属性可以合为一组。

  1. func _get_property_list():
  2. var properties = []
  3. properties.append({
  4. name = "Rotate",
  5. type = TYPE_NIL,
  6. hint_string = "rotate_",
  7. usage = PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SCRIPT_VARIABLE
  8. })
  9. # Example of adding to the group
  10. properties.append({
  11. name = "rotate_speed",
  12. type = TYPE_REAL
  13. })
  14. # This property won't get added to the group
  15. # due to not having the "rotate_" prefix.
  16. properties.append({
  17. name = "trail_color",
  18. type = TYPE_COLOR
  19. })
  20. return properties
  • name 是包含了一组属性的可折叠群组的名称;

  • 在分组属性之后添加的属性,如果带有相同前缀(由 hint_string 决定)就会被缩短。例如,这里的 rotate_speed 会被缩短为 speed。不过,movement_speed 不会成为该组的一部分,也不会被缩短。

  • PROPERTY_USAGE_GROUP 表明了该属性应被视为一个脚本分类, 因此可以忽略 TYPE_NIL 这个类型, 因为它其实并没有被脚本逻辑所处理. 但无论如何, 你还是要在这儿定义它.