Основные типы

Godot имеет богатый набор классов и шаблонов которые составляют его ядро, и все строится над ними.

Эта справка попытается перечислить их для лучшего понимания.

Определения

Godot uses the standard C99 datatypes, such as uint8_t, uint32_t, int64_t, etc. which are nowadays supported by every compiler. Reinventing the wheel for those is not fun, as it makes code more difficult to read.

В целом, не беспокойтесь об использовании самых эффективных типов данных для ваших целей, если вы конечно не используете большие структуры данных или массивы. int используется во всём коде если не нужно обратное. Это так, поскольку современные устройства имеет 32-битную шину и могут проводить операции с ними за один цикл. Также это делает код более читабельным.

Для файлов или размеров памяти, используется size_t, чтобы гарантированно иметь 64 бита.

Для строк Юникода, вместо wchar_t используется CharType, поскольку многие архитектуры имеют 4 байтовое wchar_t, где 2 байта могут быть предпочтительнее. Хотя, по умолчанию, это не обязательно и CharType напрямую переводится в wchar_t.

Источники:

Модель памяти

PC чудесная архитектура. Компьютеры часто содержат гигабайты RAM, терабайты данных и гигагерцы CPU, и когда приложению нужно больше ресурсов OS просто отдает неактивные. Другие архитектуры (такие как мобильные телефоны или консоли) в целом более ограниченны.

Самая частая модель памяти это куча, где приложение будет запрашивать область в памяти, а основная OS будет пытаться выделить её где-нибудь и вернуть указатель. Это часто работает превосходно и гибко, но с течением времени могут происходить ошибки, что ведёт к сегментации.

Сегментация медленно создаёт дыры в памяти которые слишком мелкие для возможных аллокаций, что ведет к расходу памяти. Существует много литературы описывающие кучу и сегментацию, так что эта тема будет раскрыта подробнее здесь. Современные операционные системы используют страничную память, что помогает смягчать проблему сегментации но не разрешает её.

Хотя, во многих исследованиях и тестах, было показано что даже взяв достаточно памяти, при максимальном размере аллокации меньшему чем порог пропорциональный максимальному размеру кучи и пропорциональный неиспользуемой памяти, сегментация не будет доставлять проблем со временем и будет оставаться константой. Другими словами, оставляя 10-20% вашей памяти свободной и выполняя лишь маленькие аллокации все будет в порядке.

Godot гарантирует что все объекты которые могут быть выделены динамически - маленькие (по большей части меньше чем пара килобайт). Но что если аллокация слишком большая (такая как рисунок или геометрия сеток или большой массив)? В этом случае Godot имеет опцию использования динамического пула памяти. Эта память должна быть закрыта(locked) прежде чем будет доступна, и если память для аллокации закончится, пул будет перегруппирован и сжат по усмотрению. В зависимости от потребностей игры, программист может настроить размер динамического пула.

Выделение памяти

Godot имеет много инструментов для отслеживания использования памяти в игре, особенно во время отладки. Из-за этого, обычные вызовы библиотек C и C++ не должны быть использованы. Вместо них, даны некоторые другие.

Для аллокации в стиле C, Godot предоставляет пару макросов:

memalloc()
memrealloc()
memfree()

Они эквивалентны обычным malloc, realloc, free из стандартной библиотеки C.

Для аллокаций C++, даны специальные макросы:

memnew( Class / Class(args) )
memdelete( instance )

memnew_arr( Class , amount )
memdelete_arr( pointer to array )

которые эквивалентны new, delete, new[] и delete[].

memnew/memdelete также использует маленькую магию C++ и оповещают Объекты которые они создают, перед их удалением.

Для динамической памяти, используется шаблон PoolVector<>. PoolVector это стандартный векторный класс, очень похожий на vector из стандартной библиотеки C++. Для создания PoolVector, используйте это:

PoolVector<int> data;

К PoolVector можно получить доступ через оператор [] и пара вспомогательных методов существует для этого:

PoolVector<int>::Read r = data.read()
int someint = r[4]
PoolVector<int>::Write w = data.write()
w[4] = 22;

Эти операции дают быстрый доступ записи/чтения из PoolVector'ов и сохраняют из закрытыми до тех пор пока они не покинут область видимости. Хотя, PoolVector'а должны быть использованы для маленьких, динамических операций с памятью, так как read() и write() слишком медленны для больших объёмов доступа.

Контейнеры

Godot предоставляет следующий набор контейнеров:

  • Вектор

  • Список

  • Задать

  • Карта

Они весьма просты и нацелены на то чтобы быть маленькими по возможности, как шаблоны в C++ часто встроенные(inlined) и делают размер бинарника весьма большим, для символов отладки и кода. List, Set и Map могут быть просмотрены(итерированы) через указатели, вот так:

for(List<int>::Element *E=somelist.front();E;E=E->next()) {
    print_line(E->get()); // print the element
}

Класс Vector<> также имеет пару прекрасных возможностей:

  • Он делает копию на запись, что делает создание копий очень производительным до тех пор пока их не изменяют.

  • Он поддерживает мульти-поточность, через использования атомарных операций на счётчике ссылок.

Строки

Godot также предоставляет класс строки String. Этот класс имеет большой набор возможностей, полную поддержку Юникода во всех функциях (таких как операции с регистром), парсинг/выделение utf8, а также вспомогательные функции для конверсии и визуализации.

Источники:

StringName

StringNames похожи на String, но они уникальны. Создание StringName из строки приводит созданию уникального внутреннего указателя на все одинаковые строки. StringName'ы полезны для использования строк в идентификаторах, так как их сравнение это просто сравнение указателя.

Создание StringName'а (особенно нового) медленная операция, но сравнивание - быстрая.

Источники:

Математические типы

Существует несколько типов линейной алгебры в директории core/math.

Источники:

NodePath

Это специальный тип данных для сохранения путей в дереве сцены и быстрых ссылок на них.

Источники:

RID

RID'ы это идентификаторы ресурсов. Серверы используют их для ссылки на данные сохранённые в них. RID'ы непрозрачные типы данных, что подразумевает что данные на которые они ссылаются не могут быть доступны напрямую. Все RID'ы уникальны, даже для различных типов данные на которые они ссылаются.

Источники: