This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English

Лучшие Практики

Написание кроссплатформенного кода может быть сложным, но есть способы упростить как его разработку, так и сопровождение.

Структура проекта

При создании расширения есть несколько вещей, которые помогают как в разработке, так и в поддержке.

Lua API

Должен быть только один Lua API и одна его реализация. Это значительно облегчает обеспечение одинакового поведения на всех платформах.

Если платформа не должна поддерживать расширение, рекомендуется вообще не регистрировать модуль Lua. Таким образом, можно определить поддержку, проверив значение на nil:

    if myextension ~= nil then
        myextension.do_something()
    end

Структура папок

Следующая структура папок часто используется для расширений:

    /root
        /input
        /main                            -- Все файлы для примера проекта
            /...
        /myextension                     -- Корневая папка самого расширения
            ext.manifest
            /include                     -- Внешние заголовочные файлы, используемые другими расширениями
            /libs
                /<platform>              -- Внешние библиотеки для всех поддерживаемых платформ
            /src
                myextension.cpp          -- Lua API расширения и функции жизненного цикла
                                            Также содержит универсальные реализации Lua-функций
                myextension_private.h    -- Внутренний API, который реализуется для каждой платформы (например, `myextension_Init`)
                myextension.mm           -- Для нативных вызовов на iOS/macOS. Реализует `myextension_Init` для iOS/macOS
                myextension_android.cpp  -- Для JNI вызовов на Android. Реализует `myextension_Init` для Android
                /java
                    /<platform>          -- Любые Java-файлы, необходимые для Android
            /res                         -- Ресурсы, необходимые для платформы
            /external
                README.md                -- Заметки/скрипты о сборке/упаковке внешних библиотек
        /bundleres                       -- Ресурсы, которые должны быть включены в бандл (см. game.project и [bundle_resources setting]([physics scale setting](/ru/manuals/project-settings/#project)))
            /<platform>
        game.project
        game.appmanifest                 -- Дополнительная информация о конфигурации приложения

Обратите внимание, что myextension.mm и myextension_android.cpp нужны только при использовании нативных вызовов для соответствующих платформ.

Папки платформ

В некоторых случаях архитектура платформы используется в качестве имени папки, чтобы определить, какие файлы использовать при компиляции/упаковке приложения. Формат:

<architecture>-<platform>

Текущий список:

arm64-ios, armv7-ios, x86_64-ios, arm64-android, armv7-android, x86_64-linux, x86_64-osx, x86_64-win32, x86-win32

Например, для платформоспецифичных библиотек:

/libs
    /arm64-ios
                        /libFoo.a
    /arm64-android
                        /libFoo.a

Написание нативного кода

В исходном коде Defold C++ используется очень ограниченно и преимущественно в C-стиле. Шаблоны почти не используются (за исключением некоторых контейнерных классов), так как они увеличивают время компиляции и размер исполняемого файла.

Версия C++

Исходники Defold собираются с использованием версии C++ по умолчанию для каждого компилятора. Сам движок не использует возможности C++ новее, чем C++98. Хотя использовать более новую версию для расширения возможно, это может вызвать проблемы с ABI. Это может привести к невозможности использования расширения совместно с другими расширениями движка или из портала ассетов.

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

Дополнительным плюсом является поддержание стабильного ABI, что важно для разработчиков расширений. Использование новейших возможностей C++ также может затруднить сборку под разные платформы из-за различий в поддержке.

Без исключений C++

Defold не использует исключения в движке. Исключения, как правило, не применяются в игровых движках, так как большинство данных известно на этапе разработки. Отключение поддержки исключений C++ уменьшает размер исполняемого файла и повышает производительность.

Стандартная библиотека шаблонов (STL)

В движке Defold не используется STL, за исключением некоторых алгоритмов и математических функций (std::sort, std::upper_bound и т.д.). Однако, при необходимости, вы можете использовать STL в расширении.

Следует помнить, что несовместимости ABI могут помешать использованию расширений совместно с другими расширениями или сторонними библиотеками.

Избегание STL (из-за его обширного использования шаблонов) помогает ускорить сборку и уменьшить размер исполняемого файла.

Строки

В Defold используется const char* вместо std::string. Использование std::string часто вызывает проблемы ABI при смешивании разных версий C++ или компиляторов. Применение const char* и вспомогательных функций позволяет избежать этих проблем.

Скрытие функций

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

Сторонние библиотеки

При выборе сторонней библиотеки (вне зависимости от языка), учитывайте:

  • Функциональность — решает ли она поставленную задачу?
  • Производительность — влияет ли она на работу во время выполнения?
  • Размер — насколько увеличится итоговый размер исполняемого файла?
  • Зависимости — требуется ли что-то дополнительно?
  • Поддержка — актуальность, наличие открытых проблем, активность разработки.
  • Лицензия — позволяет ли она использовать библиотеку в рамках проекта?

Зависимости с открытым исходным кодом

Убедитесь, что у вас есть доступ к зависимостям. Например, если вы полагаетесь на библиотеку из GitHub, ничто не мешает её удалению или смене владельца/направления. Чтобы снизить риск, рекомендуется создать форк и использовать его вместо оригинала.

Помните, код из этой библиотеки будет встроен в вашу игру. Убедитесь, что библиотека делает именно то, что вы от неё ожидаете — и ничего лишнего.