Variant(core/variant/variant.h)是 Godot 的动态类型容器:脚本语言、序列化、属性系统、方法调用全部通过它传递值。设计目标:小对象零分配、大对象引用计数、调用分发接近原生速度。
类型枚举
Type 枚举(variant.h:97-147)共 39 类 + VARIANT_MAX 哨兵:
| 分组 | 类型 | 数量 |
|---|---|---|
| 空 | NIL | 1 |
| 原子 | BOOL / INT / FLOAT / STRING | 4 |
| 数学 | VECTOR2, VECTOR2I, RECT2, RECT2I, VECTOR3, VECTOR3I, TRANSFORM2D, VECTOR4, VECTOR4I, PLANE, QUATERNION, AABB, BASIS, TRANSFORM3D, PROJECTION | 15 |
| 杂项 | COLOR, STRING_NAME, NODE_PATH, RID, OBJECT, CALLABLE, SIGNAL, DICTIONARY, ARRAY | 9 |
| 打包数组 | PACKED_BYTE_ARRAY … PACKED_VECTOR4_ARRAY | 10 |
存储布局
Type type + union _data(variant.h:163-267):
- 小对象内联:
_mem[]大小取sizeof(ObjData)与4*real_t较大者;float 构建下 Variant 共 24 字节 - 大对象堆分配:
_transform2d/_aabb/_basis/_transform3d/_projection经指针字段持有 - Packed 数组:引用计数的
PackedArrayRef(variant.h:194-249),多 Variant 共享底层缓冲 - OBJECT:内联
ObjData{ObjectID id; Object *obj}(variant.h:174-191);对 RefCounted 子类自动 ref/unref;needs_deinit表(:273-317)控制哪些类型需要析构
对象经 ObjectID 验活:debug 下从 Variant 取 Object 指针前用 ObjectDB::get_instance 校验,防止悬挂指针(与 object-model 的 ObjectDB 呼应)。
调用分发
Variant::call()(variant_call.cpp:1391-1420):
- OBJECT 类型 →
obj->callp()(debugger 激活时用 ObjectDB 验活) - 内建类型 → 查每类型
builtin_method_info[type]表(VariantBuiltMethodInfo{call, validated_call, ptrcall, ...});_VariantCall结构体(:669)在_register_variant_methods中注册全部内建方法
三档调用路径与 MethodBind 一致:动态 call(带 CallError)、validated_call、ptrcall。GDScript VM 对已知签名的调用走 validated 路径以跳过 Variant 装箱,见 gdscript。
与脚本/序列化的关系
- 属性系统:
Object::get/set的出入口都是 Variant,见 object-model - 场景序列化:SceneState 的属性值池就是 Variant 列表,见 scene-tree
- Callable/SIGNAL 是一等 Variant 类型,支撑信号连接的脚本侧表达
- GDExtension ABI 全部基于 Variant(或 ptrcall 的原生指针)