reckfellENGINE

Object: регистрация, отражение и владение

Текущая реализация C++, граница C#, свойства, сигналы и время жизни.

На этой странице

Статья объясняет нативную модель Object и её границу с C#. Object предоставляет отражение движка, свойства, сигналы, метаданные и уведомления. Сам по себе он не задаёт трансформацию, рендеринг или место в дереве Entity. В C# его оболочка называется ReckfellObject и отличается от System.Object.

Объявление, регистрация и отражение

Нативный наследник использует RECKFELL_CLASS(Type, Parent). Текущая реализация создаёт/инициализирует метаданные ReckfellType и нативную иерархию, затем связывает их с ClassDB. Объявление класса C++, публичность в реестре и разрешение создания — связанные, но разные факты.

Нативная регистрацияСмысл
RECKFELL_REGISTER_CLASSРегистрирует публичный класс с нативным создателем с учётом конфигурации сборки/классов.
RECKFELL_REGISTER_VIRTUAL_CLASSСтавит virtual-флаг, используемый автоматическим созданием редактором/документацией. Это не то же самое, что абстрактный класс C++; не считайте, что любой запрос явного создания обязан дать false.
RECKFELL_REGISTER_ABSTRACT_CLASSПредоставляет метаданные без обычного создателя. Проверенный CanvasItem существует, но не создаётся через ClassDB.
RECKFELL_REGISTER_INTERNAL_CLASSРегистрирует внутренние метаданные без обычного публичного доступа.
RECKFELL_REGISTER_RUNTIME_CLASSРегистрирует создатель и runtime-флаг. Из-за редакторских заглушек это не просто «тип отсутствует в редакторе».

RECKFELL_SOFT_CLASS даёт облегчённую интеграцию с Object без полного механизма регистрации RECKFELL_CLASS. Выбирайте режим осмысленно: не копируйте макросы другого SDK и не предполагайте наличие всех классов в каждой сборке/экспорте.

_bind_methods() регистрирует API при инициализации класса. Привязывайте методы через ClassDB::bind_method и D_METHOD, задавайте необязательные хвостовые аргументы через DEFVAL и сохраняйте их порядок. Одного объявления функции C++ недостаточно для соответствующего динамического API.

Нативный реестр не является отражением CLR. У C#-скрипта на Entity имя GetType().Name может отличаться от GetClass(): проверенный скрипт продолжает сообщать нативный Entity и не становится классом ClassDB под управляемым именем. Полный помощник для цепочки классов и создания нативных объектов приведён в статье о наследовании.

Свойства и динамический доступ

PropertyInfo описывает тип, нативное имя, редакторскую подсказку, её текст и usage-флаги. ADD_PROPERTY связывает метаданные с именами привязанных getter/setter. PROPERTY_USAGE_EDITOR управляет видимостью в редакторе, PROPERTY_USAGE_STORAGE участвует в сохранении; редакторское свойство не сохраняется автоматически. Обычное значение usage по умолчанию объединяет показ/хранение, но формат и реализация также имеют значение.

Hints направляют редактор, а не универсально проверяют значения из кода. Если контракту нужен предел, проверяйте его в setter. Тип enum связывайте через VARIANT_ENUM_CAST, значения — подходящими BIND_ENUM_CONSTANT/BIND_CONSTANT; объявление enum C++ само по себе не делает его доступным скриптам.

В C# при известном типе предпочитайте типизированный API: Entity2D.Position понятнее строкового поиска. Get/Set, GetIndexed/SetIndexed и доступ через ClassDB нужны инструментам, действительно работающим с неизвестными объектами. Проверенное нативное свойство — position, setter — set_position, а position:x обращается к компоненте через EntityPath. Эти имена не совпадают с PascalCase оболочки C#. ClassDB.ClassGetProperty/ClassSetProperty используют нативный путь свойств, не свойства скрипта; для скриптового пути нужны Object.Get/Set.

Метаданные класса описывают зарегистрированный тип. Object.GetPropertyList/GetMethodList также могут отражать контекст экземпляра/скрипта. Проверяйте точные имена и типы; список привязанных методов не является полным перечнем каждой специальной операции языковой оболочки.

Динамические свойства C++ используют _get, _set и _get_property_list. Макросы класса задают цепочку вызовов этих hooks; не превращайте их в посторонние virtual-переопределения по аналогии с C#-скриптом. Возвращайте true только для обработанного имени. Согласуйте список и доступ, уведомляйте через notify_property_list_changed при изменении списка. Многоуровневый порядок важен: текущий getter сначала пробует наследника, затем родителя, setter — сначала родителя.

Сигналы и метаданные

ADD_SIGNAL регистрирует описание сигнала класса. Подключение задаёт Callable и флаги; объявление само не вызывает слушателей. Обычное испускание вызывает подключённые callbacks синхронно, если не выбран deferred-режим. OneShot отключает подключение после первого вызова. Сохраняйте ту же идентичность Callable для IsConnected/Disconnect, не заменяйте захваченный callback несвязанной новой лямбдой.

Классы C# обычно используют поддерживаемые объявления/события сигналов. AddUserSignal полезен, когда динамический сигнал нужен отдельному объекту. Проверки добавляют docs_ping, находят его в метаданных экземпляра, подключают, испускают, отключают и проверяют OneShot. Пользовательский сигнал экземпляра не регистрирует новое объявление ClassDB для всех объектов типа.

Метаданные — отдельная карта именованных Variant. SetMeta/GetMeta не объявляют обычное типизированное свойство и не меняют нативный класс. Ключ должен быть допустимым идентификатором; начальное подчёркивание скрывает метаданные в обычном Inspector, но не от кода.

SetMeta с Nil удаляет запись. GetMeta для отсутствующего ключа без fallback, отличного от Nil сообщает ошибку в этой реализации. Сначала вызывайте HasMeta либо передавайте полезный явный fallback, отличный от Nil; передача Nil не является тихой проверкой наличия. RemoveMeta — явная операция удаления.

Владение и отложенная работа

Вид объектаВремя жизни
Object без RefCountedЯвное нативное владение. В C++ используйте согласованные механизмы выделения/освобождения движка, например memnew/memdelete.
EntityДерево/явное управление. Free уничтожает сразу, QueueFree планирует удаление. Уничтожение потомков и владение для сериализации сцены — разные понятия.
RefCountedВремя жизни задают нативные сильные ссылки. В C++ храните их в Ref<T>; не вызывайте memdelete для объекта, которым ещё владеет Ref.
ResourceRefCounted с поведением загрузки/хранения ресурса и необязательным путём.

Variant с Entity не делает его бессмертным. ObjectID/instance ID позволяет найти живой объект вместо хранения непроверенного сырого указателя, но не продлевает жизнь и не является постоянным ID сохранения. Проверки находят живой ID, ставят удаление в очередь, затем подтверждают отсутствие объекта по ID. Объект может быть ещё валиден и уже помечен на удаление.

Для отложенных нативных данных разрешайте ObjectDB::get_instance или Variant::get_validated_object по ситуации, не доверяя старому Object*. Проверяйте приведения через Object::cast_to<T>: неудача даёт null. Проверка валидности не синхронизирует конкурирующие потоки. В C# используйте IsInstanceValid и подходящее типизированное приведение с тем же различием времени жизни.

SetDeferred и CallDeferred ставят работу в очередь: они не выполняют её сразу и не обещают ровно следующий игровой кадр. CallDeferred не возвращает будущий результат метода синхронно. Notifications — диспетчеризация жизненного цикла движка, отдельно от сигналов и обычных вызовов; используйте нативный hook уведомлений либо C# _Notification с нужными константами.

Пути ресурсов, кэш и сохранение

Путь обозначает ресурс для загрузки/кэша, но не доказывает, что содержимое уже сохранено. У ресурса в памяти пути может не быть. Обычный ResourceLoader с reuse возвращает общий загруженный объект, а явный режим вроде Ignore допускает независимую загрузку. Поэтому правило «один загруженный экземпляр файла» не является общим ограничением.

Текущий порядок аргументов нативного сохранения — ResourceSaver::save(resource, path), в C# — ResourceSaver.Save(resource, path). Используйте подходящий актуальный формат, например .rdata. Внешние ссылки и встроенные подресурсы зависят от формата/флагов; сохранение одного объекта не сохраняет автоматически произвольное состояние приложения.

Реализация регистрации, свойств и ресурсов C++ выше сверена по исходникам; новый модуль движка не собирался. В установленном движке выполнены C#-фабрика, отражение, метаданные, сигналы, отложенные вызовы и время жизни. Все режимы регистрации, сочетания кэша, гонки времени жизни, UI редактора и платформенные сборки этим проходом не проверены.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.