Up to date

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

Класс Object

См.также

This page describes the C++ implementation of objects in Godot. Looking for the Object class reference? Have a look here.

Общее определение

Object is the base class for almost everything. Most classes in Godot inherit directly or indirectly from it. Objects provide reflection and editable properties, and declaring them is a matter of using a single macro like this:

class CustomObject : public Object {

    GDCLASS(CustomObject, Object); // this is required to inherit
};

This adds a lot of functionality to Objects. For example:

obj = memnew(CustomObject);
print_line("Object class: ", obj->get_class()); // print object class

obj2 = Object::cast_to<OtherClass>(obj); // converting between classes, this also works without RTTI enabled.

Источники:

Регистрация Object

ClassDB это статический класс который хранит полный лист зарегистрированных классов наследуемых от Object, и динамические связки для всех их методов свойств и целочисленных констант.

Классы регистрируются через вызов:

ClassDB::register_class<MyCustomClass>()

Регистрация позволяет классу быть инстанцируемым из скриптов, кода, или созданием их снова при десериализации.

Регистрация как виртуальный такое же но не может быть инстанцируемо.

ClassDB::register_virtual_class<MyCustomClass>()

Классы наследника Object могут быть перезаписаны в статической функции static void _bind_methods(). Когда один из классов регистрируется, эта статическая функция вызывается для регистрации все его методов, свойств, констант, итд. Она вызывается лишь единожды. Если класс наследник Object инстанцируется не будучи зарегистрированным, он будет автоматически зарегистрирован как виртуальный.

Внутри _bind_methods, есть целая куча вещей которые могут быть сделаны. Регистрация функций одна из них:

ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name", "arg3name"), &MyCustomType::method);

Default values for arguments can be passed as parameters at the end:

ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name", "arg3name"), &MyCustomType::method, DEFVAL(-1), DEFVAL(-2)); // Default values for arg2name (-1) and arg3name (-2).

Default values must be provided in the same order as they are declared, skipping required arguments and then providing default values for the optional ones. This matches the syntax for declaring methods in C++.

D_METHOD это макрос для конвертации "methodname" в StringName для большей эффективности. Имена аргументов используются для интроспекции, но во время компиляции для релиза, макрос игнорирует их, так что эти строки будут не использованы и выброшены при оптимизации.

Смотрите _bind_methods для Control или Object для подробных примеров.

Если просто добавить модули и функциональность которую не нужно добавлять в документацию, макрос D_METHOD() можно спокойно проигнорировать и строка с именем может быть использована для краткости.

Источники:

Константы

Классы часто содержат перечисления такие как:

enum SomeMode {
   MODE_FIRST,
   MODE_SECOND
};

For these to work when binding to methods, the enum must be declared convertible to int. A macro is provided to help with this:

VARIANT_ENUM_CAST(MyClass::SomeMode); // now functions that take SomeMode can be bound.

The constants can also be bound inside _bind_methods, by using:

BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);

Свойства (set/get)

Объекты экспортируют свойства, которые полезны для следующего:

  • Сериализации и десирализации объекта.

  • Создание списка редактируемых значений для наследуемых от Object классов.

Properties are usually defined by the PropertyInfo() class and constructed as:

PropertyInfo(type, name, hint, hint_string, usage_flags)

Например:

PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)

This is an integer property named "amount". The hint is a range, and the range goes from 0 to 49 in steps of 1 (integers). It is only usable for the editor (editing the value visually) but won't be serialized.

Другой пример:

PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")

Это строковое свойство, может брать любую строку но редактор будет разрешать только определённые подсказанные(hint). Так как не определенно флагов использования, по умолчанию это PROPERTY_USAGE_STORAGE и PROPERTY_USAGE_EDITOR.

Существует много подсказок и флагов использования доступные в object.h, проверьте их.

Свойства могут также работать как свойства C# и могут быть доступные из скрипта через индексирование, но это их использование в целом не приветствуется, так использования функций предпочтительнее для понятности. Многие свойства также разбиты на категории, такие как "animation/frame" которые делают индексирование невозможным разве что с использованием оператора [].

Из _bind_methods(), свойства могут быть созданы и связаны с соответствующими существующими функциями set/get. Например:

ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount")

Это создаёт свойство использующее сеттер и геттер.

Связывание свойств через _set/_get/_get_property_list

Дополнительный метод для создания свойств существует для достижения большей гибкости (т.е добавления или удаления свойств в контексте).

Следующие функции могут быть перезаписаны в наследнике Object, они НЕ виртуальные, НЕ ДЕЛАЙТЕ их виртуальными, они вызываются для каждой перезаписи и предыдущие не удаляются (мультиуровневый вызов).

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, к примеру:

void somefunc(Object *some_obj) {

     Button *button = Object::cast_to<Button>(some_obj);
}

Если приведение неудачно, возвращается NULL. Эта система использует RTTI, но также может хорошо работать (может немного медленно) когда RTTI отключено. Это полезно для платформ где маленькие размеры бинарного файла предпочтительнее, такое как HTML5 или консоли(с медленным доступом к памяти).

Сигналы

Objects can have a set of signals defined (similar to Delegates in other languages). This example shows how to connect to them:

obj->connect(<signal>, target_instance, target_method)
// for example:
obj->connect("enter_tree", this, "_node_entered_tree")

The method _node_entered_tree must be registered to the class using ClassDB::bind_method (explained before).

Добавление сигналов в класс делается в _bind_methods, через использование макроса ADD_SIGNAL например:

ADD_SIGNAL(MethodInfo("been_killed"))

Уведомления

All objects in Godot have a _notification method that allows it to respond to engine level callbacks that may relate to it. More information can be found on the Уведомления Godot page.

Ссылки

RefCounted inherits from Object and holds a reference count. It is the base for reference counted object types. Declaring them must be done using Ref<> template. For example:

class MyReference: public RefCounted {
    GDCLASS(MyReference, RefCounted);
};

Ref<MyReference> myref(memnew(MyReference));

myref считает ссылки. Он может быть освобождён когда нет больше шаблонов Ref<> указывающих на него.

Источники:

Ресурсы

Resource inherits from Reference, so all resources are reference counted. Resources can optionally contain a path, which reference a file on disk. This can be set with resource.set_path(path), though this is normally done by the resource loader. No two different resources can have the same path; attempting to do so will result in an error.

Ресурсы без пути тоже возможны.

Источники:

Загрузка Ресурсов

Ресурсы могут быть загружены через ResourceLoader API, например так:

Ref<Resource> res = ResourceLoader::load("res://someresource.res")

Если ссылка на этот ресурс уже загружена до этого и находится в памяти, ресурсный загрузчик вернёт эту ссылку. Это означает что только один ресурс загруженный из файла ссылается на диск в данное время.

  • resourceinteractiveloader (TODO)

Источники:

Сохранение Ресурсов

Сохранение ресурса может быть сделано через API сохранения ресурсов:

ResourceSaver::save("res://someresource.res", instance)

The instance will be saved, and sub resources that have a path to a file will be saved as a reference to that resource. Sub resources without a path will be bundled with the saved resource and assigned sub-IDs, like res://someresource.res::1. This also helps to cache them when loaded.

Источники: