Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

C# 导出属性

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

using Godot;

public partial class ExportExample : Node3D
{
    [Export]
    private int Number = 5;
}

在这个例子中,数值 5 将被保存,在构建当前项目后,它将在属性编辑器中可见。

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

导出只适用于与 Variant 兼容的类型。

备注

GDScript 中也能够导出属性,相关信息见 GDScript 导出属性

基本用法

导出包、补丁、Mod。

[Export]
private int _number;

[Export]
public int Number { get; set; }

导出的成员可以指定默认值;否则,将使用类型的 默认值

[Export]
private int _number; // Defaults to '0'

[Export]
private string _text; // Defaults to 'null' because it's a reference type

[Export]
private string _greeting = "Hello World"; // Exported field specifies a default value

[Export]
public string Greeting { get; set; } = "Hello World"; // Exported property specifies a default value

// This property uses `_greeting` as its backing field, so the default value
// will be the default value of the `_greeting` field.
[Export]
public string GreetingWithBackingField
{
    get => _greeting;
    set => _greeting = value;
}

可以导出资源和节点。

[Export]
public Resource Resource { get; set; }

[Export]
public Node Node { get; set; }

导出分组

可以使用 [ExportGroup] 特性将导出的属性分组显示在检视器中。在此特性之后的每个导出的属性都将添加到该组中。开始一个新组,或使用 [ExportGroup("")] 进行分组结束。

[ExportGroup("My Properties")]
[Export]
public int Number { get; set; } = 3;

该特性的第二个参数可用于仅将具有指定前缀的属性分组。

分组可以嵌套,请使用 [ExportSubgroup] 在分组中创建子分组。

[ExportSubgroup("Extra Properties")]
[Export]
public string Text { get; set; } = "";
[Export]
public bool Flag { get; set; } = false;

你也可以修改你的主分类的名称,或者在属性列表中使用 [ExportCategory] 特性创建额外的分类。

[ExportCategory("Main Category")]
[Export]
public int Number { get; set; } = 3;
[Export]
public string Text { get; set; } = "";

[ExportCategory("Extra Category")]
[Export]
private bool Flag { get; set; } = false;

备注

属性列表是根据类继承来组织的,而新的分类会打破这种预期。使用它们时要小心,尤其是在创建公共项目时。

字符串用作文件路径

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

字符串可以用作文件路径。

[Export(PropertyHint.File)]
public string GameFile { get; set; }

字符串也可以用作文件目录路径。

[Export(PropertyHint.Dir)]
public string GameDirectory { get; set; }

字符串在用作是文件路径时,可以在提示项中提供自定义过滤器。

[Export(PropertyHint.File, "*.txt,")]
public string GameFile { get; set; }

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

字符串还可以用作全局文件系统中某个 PNG 文件的路径。

[Export(PropertyHint.GlobalFile, "*.png")]
public string ToolImage { get; set; }

字符串也能用作全局文件系统中某个目录的路径。

[Export(PropertyHint.GlobalDir)]
public string ToolDir { get; set; }

多行文本注释会让编辑器使用大文本输入框来输入文本,而非那种小小的单行输入框。

[Export(PropertyHint.MultilineText)]
public string Text { get; set; }

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

使用范围属性提示允许你在编辑器中限制可以输入的值。

允许 0 到 20 之间的整数。

[Export(PropertyHint.Range, "0,20,")]
public int Number { get; set; }

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

[Export(PropertyHint.Range, "-10,20,")]
public int Number { get; set; }

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

[Export(PropertyHint.Range, "-10,20,0.2")]
public float Number { get; set; }

如果添加了 "or_greater" 和/或 "or_less" 的提示,在调整值时通过键入而非使用滑块,可以超过或低于限制。

[Export(PropertyHint.Range, "0,100,1,or_greater,or_less")]
public int Number { get; set; }

带缓动提示的浮点数

在编辑器里提供 'ease()' 函数的视觉呈现。

[Export(PropertyHint.ExpEasing)]
public float TransitionSpeed { get; set; }

颜色

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

[Export]
private Color Color { get; set; }

使用红、绿、蓝值指定颜色(此时Alpha 始终为 1)。

[Export(PropertyHint.ColorNoAlpha)]
private Color Color { get; set; }

节点

从 Godot 4.0 开始,节点可以直接导出,而不需要使用节点路径(NodePath)。

[Export]
public Node Node { get; set; }

也可以使用自定义节点类,参见 C# 全局类

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

[Export]
private NodePath _nodePath;

public override void _Ready()
{
    var node = GetNode(_nodePath);
}

资源

[Export]
private Resource Resource;

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

展开检查器下拉菜单可能导致一个极长的可能创建的类别列表。因此,如果你指定从 Resource 派生的类型的话:

[Export]
private AnimationNode Resource;

那么下拉菜单将只限于 AnimationNode 及其所有继承的类。也可以使用自定义的资源类,参见 C# 全局类

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

导出位标记

具有 [Flags] 特性的枚举类型的成员可以被导出,它们的值被限制为枚举类型的成员。编辑器将在检查器中创建一个小部件,允许选择枚举成员中的零个、一个或多个。该值将被存储为整数。

// Use power of 2 values for the values of the enum members.
[Flags]
public enum MyEnum
{
    Fire = 1 << 1,
    Water = 1 << 2,
    Earth = 1 << 3,
    Wind = 1 << 4,

    // A combination of flags is also possible.
    FireAndWater = Fire | Water,
}

[Export]
public SpellElements MySpellElements { get; set; }

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

// Set any of the given flags from the editor.
[Export(PropertyHint.Flags, "Fire,Water,Earth,Wind")]
public int SpellElements { get; set; } = 0;

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

你可以使用冒号添加显式的值:

[Export(PropertyHint.Flags, "Self:4,Allies:8,Foes:16")]
public int SpellTargets { get; set; } = 0;

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

[Export(PropertyHint.Flags, "Self:4,Allies:8,Self and Allies:12,Foes:16")]
public int SpellTargets { get; set; } = 0;

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

[Export(PropertyHint.Layers2DPhysics)]
public uint Layers2DPhysics { get; set; }
[Export(PropertyHint.Layers2DRender)]
public uint Layers2DRender { get; set; }
[Export(PropertyHint.Layers3DPhysics)]
public uint Layers3DPhysics { get; set; }
[Export(PropertyHint.Layers3DRender)]
public uint Layers3DRender { get; set; }

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

导出枚举

类型是枚举的成员可以导出,它们的值只能是枚举类型的成员之一。编辑器会在检查器中创建一个小部件,把以下内容列举为“Thing 1”、“Thing 2”、“Another Thing”。这个值会以整数的形式存储。

public enum MyEnum
{
    Thing1,
    Thing2,
    AnotherThing = -1,
}

[Export]
public MyEnum MyEnum { get; set; }

整数和字符串类型的成员也可以使用 [Export] 特性和 PropertyHint.Enum 提示来限制为特定的值列表。编辑器会在检查器中创建一个小部件,把以下内容列举为 Warrior、Magician、Thief。这个值会以整数的形式存储,对应于所选选项的索引(即 012 )。

[Export(PropertyHint.Enum, "Warrior,Magician,Thief")]
public int CharacterClass { get; set; };

你可以使用冒号添加显式的值:

[Export(PropertyHint.Enum, "Slow:30,Average:60,Very Fast:200")]
public int CharacterSpeed { get; set; }

如果类型是 string ,值将以字符串形式存储。

[Export(PropertyHint.Enum, "Rebecca,Mary,Leah")]
public string CharacterName { get; set; }

如果你想设置初始值,你必须明确指定它:

[Export(PropertyHint.Enum, "Rebecca,Mary,Leah")]
public string CharacterName { get; set; } = "Rebecca";

导出集合

C# Variant 文档所述,只有特定的 C# 数组和 Godot.Collections 命名空间中定义的集合类型是 Variant 兼容的,因此,只有这些类型才能被导出。

导出 Godot 数组

[Export]
public Godot.Collections.Array Array { get; set; }

使用泛型 Godot.Collections.Array<T> 可以指定数组元素的类型,这将作为编辑器的提示。检查器会限制元素为指定的类型。

[Export]
public Godot.Collections.Array<string> Array { get; set; }

Godot 数组的默认值是 null,可以指定不同的默认值:

[Export]
public Godot.Collections.Array<string> CharacterNames { get; set; } = new Godot.Collections.Array<string>
{
    "Rebecca",
    "Mary",
    "Leah",
};

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

[Export]
public Godot.Collections.Array<Texture> Textures { get; set; }

[Export]
public Godot.Collections.Array<PackedScene> Scenes { get; set; }

导出 Godot 字典

[Export]
public Godot.Collections.Dictionary Dictionary { get; set; }

使用泛型 Godot.Collections.Dictionary<TKey, TValue> 允许指定字典的键和值的元素的类型。

备注

目前在 Godot 编辑器中不支持类型化字典,因此检查器将不会限制可以分配的类型,可能导致运行时异常。

[Export]
public Godot.Collections.Dictionary<string, int> Dictionary { get; set; }

Godot 字典的默认值是 null,可以指定不同的默认值:

[Export]
public Godot.Collections.Dictionary<string, int> CharacterLives { get; set; } = new Godot.Collections.Dictionary<string, int>
{
    ["Rebecca"] = 10,
    ["Mary"] = 42,
    ["Leah"] = 0,
};

导出 C# 数组

C# 数组的元素类型是 Variant 兼容 类型,就可以导出。

[Export]
public Vector3[] Vectors { get; set; }

[Export]
public NodePath[] NodePaths { get; set; }

C# 数组的默认值是 null,可以指定不同的默认值:

[Export]
public Vector3[] Vectors { get; set; } = new Vector3[]
{
    new Vector3(1, 2, 3),
    new Vector3(3, 2, 1),
}

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

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

高级导出

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

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

参见

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

警告

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