Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

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

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++ и оповещают Объекты которые они создают, перед их удалением.

For dynamic memory, use one of Godot's sequence types such as Vector<> or LocalVector<>. Vector<> behaves much like an STL std::vector<>, but is simpler and uses Copy-On-Write (CoW) semantics. CoW copies of Vector<> can safely access the same data from different threads, but several threads cannot access the same Vector<> instance safely. It can be safely passed via public API if it has a Packed alias.

The Packed*Array types are aliases for specific Vector<*> types (e.g., PackedByteArray, PackedInt32Array) that are accessible via GDScript. Outside of core, prefer using the Packed*Array aliases for functions exposed to scripts, and Vector<> for other occasions.

LocalVector<> is much more like std::vector than Vector<>. It is non-CoW, with less overhead. It is intended for internal use where the benefits of CoW are not needed. Note that neither LocalVector<> nor Vector<> are drop-in replacements for each other. They are two unrelated types with similar interfaces, both using a buffer as their storage strategy.

List<> is another Godot sequence type, using a doubly-linked list as its storage strategy. Prefer Vector<> (or LocalVector<>) over List<> unless you're sure you need it, as cache locality and memory fragmentation tend to be more important with small collections.

Источники:

Контейнеры

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

  • Вектор

  • Список

  • Задать, установить, настроить, набор, комплект

  • Карта

They aim to be as minimal as possible, as templates in C++ are often inlined and make the binary size much fatter, both in debug symbols and code. List, Set and Map can be iterated using pointers, like this:

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

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

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

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

Источники:

Строка

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

Источники:

StrіngName

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

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

Источники:

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

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

Источники:

NоdePath

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

Источники:

RID

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

Источники: