Собственный модуль на C++
Полный набор файлов, регистрация класса, подключение к сборке, экспорт и ограничения C# SDK.
C++-модуль компилируется вместе с движком. Он подходит для изменения нативных подсистем и регистрации классов, которым нужен доступ к внутренним заголовкам. Это не подключаемая библиотека для уже установленного редактора. Для обычной игровой логики используйте C#.
Ниже — полный набор файлов учебного модуля demo_counter. Он регистрирует DemoCounter, хранит целое значение и предоставляет set_value / get_value. C++-часть сверена с исходниками, но не скомпилирована и не запущена: рабочий движок в рамках проверки не пересобирался.
Каталог модуля
Пути сборщика указаны относительно Source. Поместите шесть файлов в modules/demo_counter/ отдельной копии исходников:
modules/demo_counter/
config.py
SCsub
register_types.h
register_types.cpp
demo_counter.h
demo_counter.cppДля обнаружения нужны как минимум register_types.h, SCsub и config.py. Наличие только файла C++ не подключает модуль. Имя каталога используется в опции module_demo_counter_enabled и в именах функций инициализации; используйте уникальное имя, пригодное для идентификатора C++.
Класс и привязка методов
demo_counter.h:
#pragma once
#include "core/object/ref_counted.h"
class DemoCounter : public RefCounted {
RECKFELL_CLASS(DemoCounter, RefCounted);
int value = 0;
protected:
static void _bind_methods();
public:
void set_value(int p_value) { value = p_value; }
int get_value() const { return value; }
};demo_counter.cpp:
#include "demo_counter.h"
#include "core/object/class_db.h"
void DemoCounter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_value", "value"), &DemoCounter::set_value);
ClassDB::bind_method(D_METHOD("get_value"), &DemoCounter::get_value);
}RECKFELL_CLASS — текущий макрос для класса, регистрируемого в ClassDB. _bind_methods() открывает методы для системы вызовов движка. Объявить обычный публичный метод C++ недостаточно для вызова через эту систему. Этот минимальный пример не добавляет свойство инспектора, сериализацию значения или потокобезопасность.
Инициализация и сборка
register_types.h:
#pragma once
#include "modules/register_module_types.h"
void initialize_demo_counter_module(ModuleInitializationLevel p_level);
void uninitialize_demo_counter_module(ModuleInitializationLevel p_level);register_types.cpp:
#include "register_types.h"
#include "core/object/class_db.h"
#include "demo_counter.h"
void initialize_demo_counter_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
RECKFELL_REGISTER_CLASS(DemoCounter);
}
}
void uninitialize_demo_counter_module(ModuleInitializationLevel p_level) {
// No module-owned global resources to release.
}Генератор вызывает initialize_demo_counter_module(p_level) и uninitialize_demo_counter_module(p_level). Класс примера регистрируется только на уровне MODULE_INITIALIZATION_LEVEL_SCENE. Не используйте старые функции register_demo_counter_types() или схему MODULE_DEMO_COUNTER_HAS_PREREGISTER: текущий генератор их не вызывает.
Не вызывайте вручную удаление зарегистрированного класса при завершении. Функция uninitialize_* предназначена для принадлежащих модулю ресурсов: завершите свои фоновые задачи и освободите глобальные объекты, если они действительно созданы. В примере таких ресурсов нет.
config.py:
def can_build(env, platform):
return True
def configure(env):
passcan_build(env, platform) проверяет доступность зависимостей для конкретной платформы; True в примере означает отсутствие дополнительных ограничений. Это не доказательство успешной сборки на каждой ОС. При необходимости зарегистрируйте зависимости модулей через env.module_add_dependencies(...) и учитывайте их в can_build.
SCsub:
Import("env")
Import("env_modules")
module_env = env_modules.Clone()
module_env.add_source_files(env.modules_sources, "*.cpp")Клон env_modules сохраняет окружение модулей и изолирует дополнительные compiler flags. Объектные файлы добавляются в env.modules_sources, из которого сборщик создаёт библиотеку текущего модуля. Не меняйте глобальное env ради флагов одного модуля. Префикс # в путях SCons означает корень дерева сборки, а не корень диска.
Отдельное хранение исходников
Вместо копирования в Source/modules/ можно хранить модуль вне движка и передать каталог в custom_modules. Опция принимает пути через запятую; custom_modules_recursive по умолчанию включена. Можно передать корень самого модуля или родительский каталог. Пути нормализуются в абсолютные; они должны существовать и не должны указывать на встроенный каталог modules.
Внешний модуль с тем же именем заменяет обнаруженный встроенный. Избегайте совпадений, если замена не является целью. Выключение выполняется опцией module_demo_counter_enabled=no; после изменения конфигурации нужен новый бинарный файл.
Редактор, экспорт и C#
Сначала прочитайте подготовку сборки. Проверяйте новую сборку отдельно от установленного движка. Если класс нужен в игре, собирайте также соответствующие экспортные шаблоны: штатный шаблон класса не содержит. Укажите собственные шаблоны в профиле экспорта.
Регистрация в ClassDB не создаёт тип DemoCounter в уже установленном C# SDK. Статические C#-обёртки и glue должны соответствовать новой сборке; процесс и известные ограничения описаны в сборке с C#. Не подменяйте одну DLL в рабочем SDK наугад.
После собственной сборки проверьте регистрацию класса, создание экземпляра, запись 42, чтение 42, освобождение экземпляра и повторение в экспортированном приложении. Проверяйте именно новый бинарный файл и шаблон, а не рабочий редактор без модуля.
Если класс не появился
| Симптом | Что проверить |
|---|---|
| Модуль не обнаружен | Три обязательных файла, имя папки, путь custom_modules, глубину поиска. |
| Модуль обнаружен, но не собран | module_demo_counter_enabled, результат can_build и зависимости. |
| Ошибка линковки инициализации | Имя каталога, обе функции initialize_* / uninitialize_*, попадание register_types.cpp в сборку. |
| Класс есть, метода нет | ClassDB::bind_method, точное имя вызова и запуск нужного бинарного файла. |
| Работает в редакторе, не в экспорте | Собственный шаблон с тем же модулем и его выбор в профиле. |
C# не видит DemoCounter | Соответствие обёрток и glue новой сборке; нативная регистрация сама не меняет SDK. |
Проверены обнаружение модуля и генерация функций инициализации на изолированных примерах. Нативная компиляция, поведение класса, экспорт и управляемые обёртки остаются отдельными проверками после вашей сборки.