Object 类

参见 请看这里.

一般定义

Object 几乎是所有类的基类.Godot中的大多数类都直接或间接继承自它.Object对象提供反射和可编辑的属性, 声明它们就像使用单个宏一样.

  1. class CustomObject : public Object { GDCLASS(CustomObject, Object); // this is required to inherit};

这使得 Object 获得了很多功能,例如

  1. obj = memnew(CustomObject);print_line("Object class: ", obj->get_class()); // print object classobj2 = Object::cast_to<OtherClass>(obj); // converting between classes, this also works without RTTI enabled.

参考:

  • core/object.h

    注册对象

    ClassDB 是一个静态类,其中包含从 Object 继承的所有已注册类的完整列表,以及对其所有方法属性和整数常量的动态绑定。 通过以下调用来注册类:
    1. ClassDB::register_class<MyCustomClass>()
    注册它将允许通过脚本, 代码实例化类, 或在反序列化时再次创建它们. 注册为虚拟是相同的, 但它不能实例化.
    1. ClassDB::register_virtual_class<MyCustomClass>()
    static void _bind_methods(). 当一个类被注册时, 将调用此静态函数来注册所有对象方法, 属性, 常量等. 它只被调用一次. 如果Object派生类已实例化但尚未注册, 则它将自动注册为虚拟. _bind_methods 里面, 有几件事可以做. 注册函数是一个:
    1. ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomMethod);
    参数的默认值可以按相反的顺序传递:
    1. ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomType::method, DEFVAL(-1)); // default value for arg2name
    D_METHOD 是一个宏, 它将 methodname 转换为StringName以提高效率. 参数名称用于自我检查, 但在发布时进行编译时, 宏会忽略它们, 因此未使用字符串从而对其进行了优化. _bind_methods . D_METHOD() 宏, 并且为了简洁起见, 可以传递传递名称的字符串.

    参考:

  • core/class_db.h

    常量

    类通常有枚举, 例如:
    1. enum SomeMode { MODE_FIRST, MODE_SECOND};
    为了使这些在绑定到方法时起作用, 枚举必须被声明为可转换为int, 为此提供了一个宏:
    1. VARIANT_ENUM_CAST(MyClass::SomeMode); // now functions that take SomeMode can be bound.
    _bind_methods 中, 通过使用:
    1. BIND_CONSTANT(MODE_FIRST);BIND_CONSTANT(MODE_SECOND);

    属性(设置/获取)

    对象导出属性, 这些属性可用于以下用途:
  • 序列化和反序列化对象.
  • 为Object派生类创建可编辑值列表. 属性通常由PropertyInfo()类定义. 通常构造为:
    1. PropertyInfo(type, name, hint, hint_string, usage_flags)
    例如:
    1. PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)
    amount, hint 是一个范围, 范围从0到49, 步长为1(整数). 它仅适用于编辑器(可视化编辑值), 但不会被序列化. 另一个示例:
    1. PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")
    PROPERTY_USAGE_STORAGEPROPERTY_USAGE_EDITOR. 在object.h中有很多提示和用法标记, 请对其进行检查. 动画/帧, 除非使用操作符 [], 否则也无法建立索引. _bind_methods() 开始, 只要存在set/get函数, 就可以创建和绑定属性. 例如:
    1. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount")
    这将使用setter和getter创建属性.

    使用 _set/_get/_get_property_list 绑定属性

    当需要更大的灵活性时(即在上下文中添加或删除属性), 存在另一种创建属性的方法. 可以在Object派生类中重写以下函数, 它们不是虚拟的, 不要将它们设置为虚拟, 它们会在每次重写时调用, 而之前的函数不会失效(多级调用).
    1. protected: void _get_property_list(List<PropertyInfo> *r_props) const; // return list of properties bool _get(const StringName &p_property, Variant &r_value) const; // return true if property was found bool _set(const StringName &p_property, const Variant &p_value); // return true if property was found
    p_property 必须按顺序与所需的名称进行比较, 因此效率也较低.

    动态转型

    Godot在Object派生类之间提供动态转换, 例如:
    1. void somefunc(Object *some_obj) { Button *button = Object::cast_to<Button>(some_obj);}
    如果强制转换失败, 则返回NULL. 这个系统使用RTTI, 但是当RTTI被禁用时它也可以正常工作(虽然有点慢). 这在二进制大小较小的平台上非常有用, 例如HTML5或游戏主机(具有较小的内存占用).

    信号

    对象可以定义一组信号(类似于其他语言的代理). 连接它们很容易:
    1. obj->connect(<signal>, target_instance, target_method)// for example:obj->connect("enter_tree", this, "_node_entered_tree")
    _node_entered_tree 方法必须使用 ClassDB::bind_method (前面解释过)注册到类. ADD_SIGNAL 宏在 _bind_methods 中添加信号到类中, 例如:
    1. ADD_SIGNAL(MethodInfo("been_killed"))

    参考

    Reference 继承自Object并保存引用计数. 它是引用计数对象类型的基础. 必须使用Ref<>模板来声明它们. 例如:
    1. class MyReference: public Reference { GDCLASS(MyReference, Reference);};Ref<MyReference> myref(memnew(MyReference));
    myref 是引用计数. 当没有更多Ref<>模板指向它时, 它将被释放.

    参考:

  • core/reference.h

    资源:

    Resource 继承自Reference, 因此所有资源都被引用计数. 资源可以选择包含引用磁盘上文件的路径. 这可以用 resource.set_path(path) 设置. 这通常由资源加载器完成. 没有两个不同的资源可以具有相同的路径, 尝试这样做会导致错误. 资源也可以没有路径.

    参考:

  • core/resource.h

    资源加载

    可以使用ResourceLoader API加载资源, 如下所示:
    1. Ref<Resource> res = ResourceLoader::load("res://someresource.res")
    如果先前已加载对该资源的引用并且该引用在内存中, 则资源加载器将返回该引用. 这意味着只能同时从磁盘上引用的文件加载一个资源. -

    参考:

  • core/io/resource_loader.h

    资源保存

    可以使用资源保存器API保存资源:
    1. ResourceSaver::save("res://someresource.res", instance)
    res://someresource.res::1。这也有助于在加载时对其进行缓存。

    参考:

  • core/io/resource_saver.h