Object 类
最后同步日期:2026-04-15 | Godot 官方原文 — Object class
Object 类
Object 是 Godot 引擎中几乎所有东西的基类。你在引擎中看到的 Node、Resource、Control、ResourceLoader……它们的"族谱"往上追溯,最终都会指向 Object。
打个比方:Object 就像是乐高积木的"基础接口"——它定义了所有积木块都必须遵守的基本规则,比如"如何描述自己"、"如何响应外部请求"、"如何被序列化保存"等。
基本定义
要让一个类成为 Godot 的"合法公民",只需要继承 Object 并加上一个宏:
class CustomObject : public Object {
GDCLASS(CustomObject, Object); // 继承声明,必须添加
};这一行 GDCLASS 宏就像给你的类发了一张"身份证",它会给你的类自动添加一大堆功能:
// 创建对象实例
CustomObject *obj = memnew(CustomObject);
// 打印类名(运行时反射)
print_line("Object class: ", obj->get_class());
// 安全的类型转换(不需要 RTTI 也能工作)
OtherClass *obj2 = Object::cast_to<OtherClass>(obj);源码参考:
core/object/object.h
在 ClassDB 中注册类
ClassDB 是 Godot 的"类注册中心"——一个静态类,保存着所有已注册类的信息,包括它们的方法、属性和常量。
普通注册
// 注册后,这个类可以被脚本实例化、序列化和反序列化
ClassDB::register_class<MyCustomClass>();虚拟类注册
// 注册为虚拟类——不能直接实例化,但可以被继承
ClassDB::register_virtual_class<MyCustomClass>();如果一个 Object 派生类被实例化了但还没注册,引擎会自动将它注册为虚拟类。
绑定方法
每个 Object 派生类都可以重写静态函数 _bind_methods()。当类被注册时,这个函数会被调用一次,用来注册方法、属性和常量:
void MyCustomType::_bind_methods() {
// 绑定方法,参数名用于脚本层面的内省(Introspection)
ClassDB::bind_method(D_METHOD("methodname", "arg1", "arg2"), &MyCustomType::method);
// 带默认值的参数
ClassDB::bind_method(
D_METHOD("methodname", "arg1", "arg2", "arg3"),
&MyCustomType::method,
DEFVAL(-1), // arg2 的默认值为 -1
DEFVAL(-2) // arg3 的默认值为 -2
);
}D_METHOD 宏会将方法名转换为 StringName(之前介绍过的字符串名称),提高查找效率。在发布版本中,参数名会被优化掉,不会增加二进制体积。
源码参考:
core/object/class_db.h
常量绑定
类中经常使用枚举(enum)来定义一组相关的常量:
enum SomeMode {
MODE_FIRST,
MODE_SECOND
};要让枚举能在绑定方法中使用,需要用宏将其转换为 int:
VARIANT_ENUM_CAST(MyClass::SomeMode);在 _bind_methods() 中,还可以将常量暴露给脚本:
void MyClass::_bind_methods() {
BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);
}属性(Properties)
属性是 Object 系统的核心特性之一。它让对象可以被序列化、反序列化,并在编辑器中显示为可编辑的字段。
属性信息
属性通过 PropertyInfo 类来定义:
PropertyInfo(type, name, hint, hint_string, usage_flags)一个实际的例子:
// 整数属性 "amount",范围 0~49,步长 1,仅在编辑器中可见
PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)另一个例子:
// 字符串属性 "modes",在编辑器中显示为下拉选项
PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")绑定属性
在 _bind_methods() 中,只要有对应的 setter 和 getter,就可以创建属性:
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount");动态属性
当需要更灵活的属性管理(比如根据上下文动态增删属性)时,可以重写以下方法:
protected:
// 返回属性列表
void _get_property_list(List<PropertyInfo> *r_props) const;
// 获取属性值,找到返回 true
bool _get(const StringName &p_property, Variant &r_value) const;
// 设置属性值,找到返回 true
bool _set(const StringName &p_property, const Variant &p_value);注意
这些方法不是虚函数(virtual),不要加 virtual 关键字。引擎会依次调用继承链中所有类的实现,之前的实现不会被覆盖。
动态类型转换
Godot 提供了安全的类型转换机制,即使禁用了 C++ 的 RTTI 也能正常工作:
void some_func(Object *some_obj) {
// 尝试将 Object 转换为 Button
Button *button = Object::cast_to<Button>(some_obj);
if (button != nullptr) {
// 转换成功,可以安全使用 button
button->set_text("Click me");
}
}转换失败时返回 nullptr。这种方式在 HTML5 等需要最小二进制体积的平台上尤其有用。
信号(Signals)
信号是 Godot 中的"事件广播"机制——类似于其他语言中的委托(Delegate)或事件(Event)。
连接信号
// 连接信号到目标对象的方法
obj->connect("enter_tree", this, "_node_entered_tree");目标方法(如 _node_entered_tree)必须通过 ClassDB::bind_method 注册过。
添加信号
在 _bind_methods() 中,使用 ADD_SIGNAL 宏为类添加信号:
ADD_SIGNAL(MethodInfo("been_killed"));通知(Notifications)
所有 Object 都有一个 _notification 方法,用于接收引擎层面的回调通知。引擎会在特定时机(如进入场景树、退出场景树、进程更新等)向对象发送通知。
更详细的通知列表和用法,可以参考 Godot 官方文档的通知页面。
引用计数:RefCounted
RefCounted 继承自 Object,增加了一个引用计数器。当没有任何 Ref<> 指针指向它时,对象会自动被释放。
class MyReference : public RefCounted {
GDCLASS(MyReference, RefCounted);
};
// 使用 Ref<> 模板管理引用计数
Ref<MyReference> myref(memnew(MyReference));源码参考:
core/object/reference.h
资源(Resources)
Resource 继承自 RefCounted,所以所有资源都是引用计数的。资源可以关联一个磁盘上的文件路径,通过 resource.set_path(path) 设置。
注意
同一时间不能有两个不同的资源使用相同的路径——引擎会报错。没有路径的资源也是合法的。
源码参考:
core/io/resource.h
资源加载与保存
加载资源
// 从磁盘加载资源(如果已加载过,会返回缓存中的引用)
Ref<Resource> res = ResourceLoader::load("res://someresource.res");ResourceLoader 会缓存已加载的资源。同一个文件在同一时间只会被加载一份——所有对它的请求都共享同一个实例。
保存资源
// 将资源保存到磁盘
ResourceSaver::save("res://someresource.res", instance);保存时,有路径的子资源会被保存为引用;没有路径的子资源会被打包进主资源中,分配子 ID(如 res://someresource.res::1)。
源码参考:
core/io/resource_loader.h、core/io/resource_saver.h
