Variant
Godot 中最重要的数据类型。
描述
在计算机编程中,Variant(变体)类是用来存储各种其他类型的类。像 PHP、 Lua、 JavaScript 和 GDScript 这样的动态编程语言喜欢用它们在后端存储变量数据。使用 Variant,属性可以自由地更改值类型。
GDScriptC#
var foo = 2 # foo 是动态类型的整数
foo = "现在 foo 是字符串!"
foo = RefCounted.new() # foo 是 Object
var bar: int = 2 # bar 是静态类型的整数。
# bar = "诶呀!我没法让静态类型的变量变成其他类型!"
// C# 是静态类型的。变量设置类型后无法改变。你可以用 `var` 关键字让编译器自动推断类型。
var foo = 2; // foo 是 32 位整数(int)。请注意,GDScript 中的整数是 64 位的,在 C# 中与之等价的是 `long`。
// foo = "foo 过去、现在、将来都是整数,没法变成字符串!";
var boo = "boo 是字符串!";
var ref = new RefCounted(); // var 非常适合与构造函数配合使用。
// Godot 也提供了 Variant 类,类似于一个与所有 Variant 兼容类型的联合体。
Variant fooVar = 2; // fooVar 是动态类型的整数(在 Variant 类型中存储为 `long`)。
fooVar = "现在 fooVar 是字符串!";
fooVar = new RefCounted(); // fooVar 是 GodotObject。
Godot 在 Variant 中跟踪所有脚本 API 变量。你一直在无意中使用 Variant。某种语言为保持数据类型而执行自己的规则时,那么就是该语言在基础 Variant 脚本 API 上应用了自定义的逻辑。
GDScript 会自动将数值进行包装。默认情况下会将所有数据保存在普通的 Variant 中,也可以选择对变量类型执行自定义的静态类型规则。
C# 是静态类型的,但是当它需要表示动态值时,就会在需要 Godot 的 Variant 类的地方使用它自己实现的 Variant 类型。C# Variant 可以用任意兼容类型隐式赋值,但反之则需要显式类型转换。
全局函数 @GlobalScope.typeof 返回的是枚举类型的值,表示当前变量中所存储的 Variant 类型(见 Variant.Type)。
GDScriptC#
var foo = 2
match typeof(foo):
TYPE_NIL:
print("foo 为 null")
TYPE_INT:
print("foo 为整数")
TYPE_OBJECT:
# 请注意,Object 有自己的特殊分类。
# 要获取实际的 Object 类型名称,你需要使用 `get_class()` 方法。
print("foo is a(n) %s" % foo.get_class()) # 将类名注入格式字符串中。
# 请注意,获取到的并不是脚本的 `class_name` 全局名称。
# 如果要获取 `class_name`,请改用 `foo.get_script().get_global_name()`。
Variant foo = 2;
switch (foo.VariantType)
{
case Variant.Type.Nil:
GD.Print("foo 为 null");
break;
case Variant.Type.Int:
GD.Print("foo 为整数");
break;
case Variant.Type.Object:
// 请注意,Object 有自己的特殊分类。
// 可以将 Variant 转换为 GodotObject,通过反射获取名称。
GD.Print($"foo is a(n) {foo.AsGodotObject().GetType().Name}");
break;
}
Variant 只占 20 个字节,可以在其中存储几乎所有的引擎数据类型。Variant 很少用于长期保存信息,主要还是用于通信、编辑、序列化和移动数据。
Godot 特别致力于使其 Variant 类尽可能灵活;以使它可被用于各种操作,促进 Godot 所有系统之间的联系。
Variant:
可以存储几乎任何数据类型。
可以在许多 Variant 之间执行操作。GDScript 使用 Variant 作为其原子/原生数据类型。
可以被哈希,所以可以快速与其他 Variant 进行比较。
可以用于数据类型之间的安全转换。
可以用来抽象调用方法和它们的参数。Godot 通过 Variant 导出所有函数。
可以用来推迟调用或在线程之间移动数据。
可以序列化为二进制并存储到磁盘,或通过网络传输。
可以序列化为文本,用于打印数值和可编辑设置项。
可以作为一个导出的属性工作,所以编辑器可以通用地进行编辑。
可以用于字典、数组、解析器等。
容器(数组和字典):它们都是用 Variant 来实现的。Dictionary 可以将任何作为键的数据类型匹配到到任何其他数据类型。Array 就是持有 Variant 的数组。当然,Variant 也可以在里面再容纳 Dictionary 和 Array,使其更加灵活。
对容器的修改会修改所有对它的引用。如果需要多线程访问,应该创建 Mutex 来对它进行锁定。
备注
通过 C# 使用该 API 时会有显著不同,详见 C# API 与 GDScript 的差异。