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 обладает обширной встроенной системой пользовательского интерфейса, а небольшой размер дистрибутива может сделать его подходящей альтернативой таким фреймворкам, как Electron или Qt.

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

Примечание

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

См. также

Загляните в Material Maker и Pixelorama для примеров приложений с открытым исходным кодом, созданных с помощью Godot.

Выполнение типовых задач

Создание нескольких окон

Это поддерживается только в Windows, macOS и Linux (только X11/XWayland, не в родном режиме Wayland).

Дополнительные окна можно создавать с помощью узла Window. Окна можно перемещать, изменять их размер, сворачивать и закрывать независимо от главного окна приложения.

Однако если закрыть главное окно, все остальные окна также закроются, поскольку закрытие главного окна завершает процесс. Этого можно избежать, свернув главное окно, установив его свойство unfocusable в true (чтобы скрыть его с панели задач и переключателя задач), а затем создав дополнительные узлы Window сразу при запуске. Не забудьте в этом случае предусмотреть альтернативный способ выхода из приложения, например значок в трее.

Ограничение размера окна

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

Ограничения размера можно задать с помощью свойств min_size и max_size узла Window. Не забудьте умножить эти ограничения в соответствии с коэффициентом масштабирования приложения (см. Масштабирование для дисплеев с высоким DPI).

Совет

Напомним, что вы можете получить корневой узел Window и задать его свойства с помощью get_window() для любого узла.

Использование нативных диалогов выбора файлов

Это поддерживается только в Windows, macOS, Linux и Android.

По умолчанию Godot использует собственную реализацию FileDialog для диалогов выбора файлов. Однако вы можете использовать нативные диалоги операционной системы. Пользователи обычно предпочитают этот вариант, так как нативные диалоги лучше интегрируются в среду рабочего стола и обеспечивают более привычный интерфейс.

Вы можете включить нативные диалоги, установив свойство use_native_dialog узла FileDialog. Это необходимо сделать для каждого узла FileDialog, используемого в проекте, поскольку не существует глобальной настройки проекта для управления этим поведением.

Сравнение стандартного FileDialog (слева) и нативного диалога выбора файлов (справа) в macOS

Сравнение стандартного FileDialog (слева) и нативного диалога выбора файлов (справа) в macOS

Примечание

См. описание свойства для подробностей о поддержке на разных платформах.

Кроме того, в macOS нативные диалоги файлов не поддерживаются, если в редакторе включена встраивание игры. Чтобы протестировать эту функцию при запуске проекта, отключите встраивание игры, переключившись на экран Game, нажав крайний правый значок в верхней панели и сняв флажок Embed Game on Next Play.

Создание значка в системном трее

Это поддерживается только в Windows и macOS.

Вы можете создать один или несколько значков в системном трее (также называемом областью уведомлений) с помощью узла StatusIndicator. Помимо всплывающей подсказки, этому узлу можно назначить узел PopupMenu, чтобы при щелчке по значку отображалось выпадающее меню.

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

После создания значка в трее вы также можете реализовать поведение «сворачивать при закрытии». Это означает, что когда пользователь пытается закрыть приложение с помощью кнопки X оконного менеджера, оно сворачивается в трей. Для этого прикрепите этот скрипт к автозагружаемой сцене с узлом StatusIndicator в качестве корневого:

extends StatusIndicator

# Disable this behavior when running from the editor with game embedding,
# as it doesn't cooperate well.
var tray_icon_supported = (
        DisplayServer.has_feature(DisplayServer.FEATURE_STATUS_INDICATOR)
        and not Engine.is_embedded_in_editor()
    )


func _ready():
    visible = false

    if tray_icon_supported:
        get_tree().auto_accept_quit = false
        get_window().focus_entered.connect(
                func():
                    # Hide the tray icon when the window gains focus,
                    # which means it was restored from its minimized state.
                    visible = false
            )
        pressed.connect(
                func(_mouse_button, _position):
                    # Restore the application when the tray icon is clicked.
                    get_window().mode = Window.MODE_WINDOWED
            )


func _notification(what):
    if not tray_icon_supported:
        return

    match what:
        NOTIFICATION_WM_CLOSE_REQUEST:
            get_window().mode = Window.MODE_MINIMIZED
            # Show the tray icon.
            visible = true

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

Примечание

Если присутствует несколько узлов StatusIndicator, их порядок в системном трее определяется порядком их добавления в дерево сцены.

Использование глобального меню

Это поддерживается только в macOS.

В macOS приложения могут использовать глобальную строку меню системы вместо отображения строки меню внутри окна приложения. В Godot это также называется нативным меню.

Сравнение стандартного MenuBar (слева), MenuBar с нативными всплывающими окнами (в центре) и нативного меню (справа) в macOS

Сравнение стандартного MenuBar (слева), MenuBar с нативными всплывающими окнами (в центре) и нативного меню (справа) в macOS

Godot поддерживает создание меню через узел MenuBar, который отображает свои дочерние элементы PopupMenu в качестве меню. Вы можете включить поддержку глобального меню для данного узла MenuBar, установив в инспекторе его свойство prefer_global_menu. В macOS это приведёт к тому, что узел MenuBar исчезнет и не будет занимать место, а его меню будут отображаться в глобальной строке меню системы. Если это свойство отключено, узел MenuBar будет отображать свои меню внутри окна приложения, как обычно, но при поддержке операционной системой всё равно будут использоваться нативные всплывающие окна.

Примечание

Меню приложения (с названием проекта, выделенным жирным шрифтом), а также меню Window и Help всегда присутствуют в macOS. Не следует добавлять их в глобальное меню вручную.

В Godot 4.6 и новее вы можете добавлять новые пункты в эти меню, изменив свойство system_menu_id узла PopupMenu. Вы можете выбрать между Application Menu (первое меню с названием приложения, выделенным жирным шрифтом), Window Menu, Help Menu и Dock (отображается при щелчке правой кнопкой мыши по значку в Dock). Стандартные пункты меню, уже присутствующие в этих меню, будут сохранены:

Пользовательские опции, добавленные в системное меню Window в macOS

Пользовательские опции, добавленные в системное меню Window в macOS

Проект может содержать несколько узлов MenuBar. Если для нескольких узлов MenuBar включено свойство Prefer Global Menu, параметры меню будут добавлены по индексу, определяемому свойством Start Index, при добавлении узла MenuBar в дерево сцены. Это позволяет размещать контекстно-зависимые меню в конце строки меню, чтобы первые пункты меню оставались на месте при добавлении или удалении дополнительной строки меню.

Для более сложных случаев использования вы также можете использовать синглтон NativeMenu напрямую, без использования узла MenuBar.

Примечание

Интеграция с глобальным меню не поддерживается, если в редакторе включена встраивание игры. Чтобы протестировать эту функцию при запуске проекта, отключите встраивание игры, переключившись на экран Game, нажав крайний правый значок в верхней панели и сняв флажок Embed Game on Next Play.

Использование клиентских декораций

Это поддерживается только в macOS.

Многие современные приложения используют клиентские декорации (CSD) вместо того, чтобы полагаться на оконный менеджер операционной системы для отрисовки заголовка и границ окна (серверные декорации). Это позволяет добиться более настраиваемого внешнего вида и лучшей интеграции с интерфейсом приложения.

В настоящее время Godot поддерживает клиентские декорации только в macOS. Их можно использовать, включив настройку проекта display/window/size/extend_to_title.

Сравнение стандартных декораций окна (вверху) и клиентских декораций (внизу) в macOS

Сравнение стандартных декораций окна (вверху) и клиентских декораций (внизу) в macOS

После включения клиентских декораций граница окна больше не отображается, а кнопки свернуть/развернуть/закрыть будут показаны в виде наложения на приложение. Убедитесь, что приложение обеспечивает достаточный отступ сверху для комфортного отображения кнопок, а также отображает заголовок окна с помощью узла Label или аналогичного.

Чтобы условно адаптировать интерфейс в зависимости от того, включены ли клиентские декорации, используйте DisplayServer.has_feature, а также проверьте текущее значение Window.extend_to_title (именно его изменяет настройка проекта):

func _ready():
    if DisplayServer.has_feature(FEATURE_EXTEND_TO_TITLE) and get_window().extend_to_title:
        # Adjust UI for client-side decorations (a MarginContainer node
        # can be useful here). Also set the window title to be displayed
        # according to the native window title.
        $WindowTitle.visible = true
        $WindowTitle.text = get_window().title
        if OS.is_debug_build():
            $WindowTitle.text += " (DEBUG)"

Для правильного позиционирования заголовка окна рассмотрите возможность использования DisplayServer.window_get_safe_title_margins(), которая возвращает Vector3, где x — левый отступ, y — правый отступ (будет увеличиваться, если в системе используется набор текста справа налево), а z — высота. Кроме того, вы можете вызвать DisplayServer.window_set_window_buttons_offset(), чтобы настроить положение кнопок закрытия/свертывания/развертывания (обычно для их вертикального выравнивания по центру).

Безопасные отступы заголовка при использовании клиентских декораций в macOS

Безопасные отступы заголовка при использовании клиентских декораций в macOS

Примечание

В macOS клиентские декорации не поддерживаются, если в редакторе включена встраивание игры. Чтобы протестировать эту функцию при запуске проекта, отключите встраивание игры, переключившись на экран Game, нажав крайний правый значок в верхней панели и сняв флажок Embed Game on Next Play.

Отображение статуса прогресса на панели задач/Dock

Это поддерживается только в Windows и macOS.

Приложения могут сообщать операционной системе статус прогресса, который может отображаться на панели задач или значке Dock. Этот статус состоит из состояния (активно, приостановлено, ошибка) и процента выполнения. Это можно использовать для отображения прогресса, когда пользователь не сосредоточен на приложении.

Отображение прогресса в Dock в macOS

Отображение прогресса в Dock в macOS

Это часто достигается синхронизацией прогресса узла ProgressBar с прогрессом, сообщаемым операционной системе:

func set_progress(value, indeterminate = false):
    $ProgressBar.value = value
    $ProgressBar.indeterminate = indeterminate

    if $ProgressBar.indeterminate:
        get_window().set_taskbar_progress_state(DisplayServer.PROGRESS_STATE_INDETERMINATE)
    else:
        get_window().set_taskbar_progress_state(DisplayServer.PROGRESS_STATE_NORMAL)

    # The taskbar progress value must be between `0.0` and `1.0`
    # (values outside this range are clamped).
    # ProgressBar provides a `ratio` property that represents its current progress
    # as a value between `0.0` and `1.0`.
    get_window().set_taskbar_progress_value($ProgressBar.ratio)

Доступно несколько состояний прогресса: нет прогресса (скрывает индикатор), неопределённый, обычный, приостановлен, ошибка. Подробности см. в справочнике классов.

Вы также можете использовать Window.request_attention(), чтобы заставить окно мигать на панели задач (или подпрыгивать в Dock в macOS). Например, это можно использовать для привлечения внимания пользователя после завершения длительной операции.

Примечание

Отображение прогресса не поддерживается, если в редакторе включена встраивание игры. Чтобы протестировать эту функцию при запуске проекта, отключите встраивание игры, переключившись на экран Game, нажав крайний правый значок в верхней панели и сняв флажок Embed Game on Next Play.

Отправка уведомлений рабочего стола

В настоящее время Godot не имеет встроенной поддержки отправки уведомлений рабочего стола.

Однако в macOS и Linux вы можете использовать утилиты командной строки osascript и notify-send соответственно для отправки уведомлений рабочего стола:

func send_notification(title, message):
    var app_name = ProjectSettings.get_setting("application/config/name")
    if app_name.is_empty():
        app_name = "Unnamed Project"

    if OS.has_feature("macos") and not OS.is_sandboxed():
        # Note that this will not work if the project is exported in sandbox mode
        # (e.g. for the Mac App Store).
        OS.execute("osascript", [
                "-e",
                'display notification \\"%s\\" with title \\"%s\\" subtitle \\"%s\\"' % [
                    message,
                    app_name,
                    title,
                ]
            ])
    elif OS.has_feature("linuxbsd"):
        OS.execute("notify-send", ["--app-name", app_name, title, message])

func _ready():
    send_notification("Success", "Operation completed successfully.")

К сожалению, в Windows нет эквивалента, доступного «из коробки».

Запоминание положения и размера окна между сеансами

Godot не имеет встроенной поддержки запоминания положения и размера окна между сеансами, но это можно реализовать вручную с помощью скрипта. Простой пример, поддерживающий многомониторные конфигурации, — это автозагрузка со следующим скриптом:

extends Node

# Use a dedicated configuration file for the window state.
# This way, the application's other configuration files are left
# untouched and can be put in version control without unnecessary diffs
# being produced.
const CONFIG_WINDOW_PATH = "user://window.ini"

var config_file = ConfigFile.new()


func _enter_tree():
    config_file.load(CONFIG_WINDOW_PATH)

    # Do not restore previous window state if running from the editor
    # with game embedding enabled.
    if not Engine.is_embedded_in_editor():
        var window_screen = config_file.get_value("main", "screen", -1)
        if window_screen is int:
            get_window().current_screen = window_screen

        var window_mode = config_file.get_value("main", "mode", -1)
        if window_mode is Window.Mode:
            get_window().mode = window_mode

        var window_position = config_file.get_value("main", "position", -1)
        if window_position is Vector2i:
            get_window().position = window_position

        var window_size = config_file.get_value("main", "size", -1)
        if window_size is Vector2i:
            get_window().size = window_size


func _exit_tree():
    # Save the current window state when the application is quit normally.
    # In a real world scenario, it's recommended to also save this information
    # regularly (e.g. with a Timer node), so that the window state can be
    # restored after a crash or when terminated externally.
    config_file.set_value("main", "screen", get_window().current_screen)
    config_file.set_value("main", "mode", get_window().mode)
    config_file.set_value("main", "position", get_window().position)
    config_file.set_value("main", "size", get_window().size)
    config_file.save(CONFIG_WINDOW_PATH)

Примечание

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

Скрытие окна во время заставки

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

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

Для этого настройки проекта должны быть настроены следующим образом:

Этот скрипт можно использовать как автозагрузку, чтобы восстановить исходные настройки после завершения отображения заставки:

extends Node


func _enter_tree():
    # Wait a frame to be rendered before restoring the window properties.
    # Otherwise, properties will be restored too early and the window border
    # will show up around a transparent window.
    await get_tree().process_frame

    get_viewport().transparent_bg = false
    get_window().transparent = false
    get_window().borderless = false
    get_window().size = Vector2i(1152, 648)

Отображение приложения в виде наложения

Можно отобразить окно приложения в виде наложения, которое всегда находится поверх других окон. Это может быть полезно для таких приложений, как виджеты или системные мониторы.

Для этого включите все следующие настройки проекта:

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

Чтобы разрешить вводу мыши проходить к фоновому приложению, установите свойство mouse_passthrough в true для окна, отображаемого в качестве наложения. Вы также можете определить многоугольник в mouse_passthrough_polygon, чтобы определённые области по-прежнему могли перехватывать ввод мыши в наложении.

Кроме того, вы можете установить свойство exclude_from_capture в true, чтобы предотвратить появление наложения на скриншотах или в записях. Эта подсказка реализована только в Windows и macOS и предоставляется по принципу «насколько возможно», поэтому её не следует использовать как абсолютную меру безопасности или DRM.

Примечание

Отображение в виде наложения не поддерживается, если в редакторе включена встраивание игры. Чтобы протестировать эту функцию при запуске проекта, отключите встраивание игры, переключившись на экран Game, нажав крайний правый значок в верхней панели и сняв флажок Embed Game on Next Play.

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

Существуют также известные проблемы с отображением прозрачных окон в Windows при использовании гибридных конфигураций GPU (например, NVIDIA Optimus). Переключение рендерера может помочь решить проблему.

В Linux с X11 прозрачность не будет работать, если пользователь отключил композитинг в настройках оконного менеджера.

Масштабирование для дисплеев с высоким DPI

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

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

Примечание

В настоящее время Godot поддерживает чтение коэффициента масштабирования экрана из настроек ОС только в macOS, Android и Linux (только Wayland). В Linux (X11) и Windows вам нужно будет предоставить пользователю возможность ручной настройки масштаба интерфейса.

Интеграция со скринридерами

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

Godot автоматически включает поддержку скринридеров, если обнаруживает, что скринридер запущен. Это можно настроить в настройках проекта с помощью accessibility/general/accessibility_support, чтобы отключить её в ситуациях, когда она нежелательна. Её также можно принудительно включить, что полезно при использовании инструментов отладки доступности, которые не распознаются Godot как скринридеры.

Godot использует библиотеку AccessKit для интеграции со скринридерами.

Совет

Поскольку поддержка скринридеров использует само приложение скринридера для воспроизведения звука (а не проект Godot), она будет работать даже если звуковой драйвер установлен в Dummy в настройках проекта, как описано ниже.

Настоятельно рекомендуется тестировать ваше приложение с популярными скринридерами на целевых платформах, чтобы обеспечить хороший пользовательский опыт для людей с нарушениями зрения. Примеры включают NVDA в Windows, VoiceOver в macOS и Orca в Linux.

Чтобы обеспечить хороший уровень удобства поддержки скринридеров, требуется значительный объём работы. Необходимо определить метки доступности с помощью свойств Control.accessibility_name и Control.accessibility_description, а также убедиться, что интерфейс читается в логическом порядке скринридером.

См. также

См. также Текст в речь о функции синтеза речи, которая существует отдельно от скринридеров.

Добавление модульных тестов

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

GDScript не имеет встроенной среды модульного тестирования, но существуют несколько плагинов для модульного тестирования, поддерживаемых сообществом:

  • Gut

  • GdUnit4 (также поддерживает C#)

С C# и GDExtension (C++, Rust и т. д.) вы можете использовать стандартные среды тестирования, такие как NUnit или doctest.

Оптимизация размера дистрибутива

Поскольку неигровые приложения обычно не используют большие части движка, такие как звук или 3D-функциональность, вы можете скомпилировать оптимизированный шаблон экспорта для уменьшения его размера. Это также улучшит время запуска, особенно на веб-платформе, где размер бинарного файла напрямую связан со скоростью инициализации.

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

Создание дистрибутива в виде одного исполняемого файла

По умолчанию Godot создаёт PCK-файл, содержащий данные проекта, рядом с исполняемым файлом. Это означает, что если переместить исполняемый файл без одновременного перемещения PCK-файла, приложение не запустится. Это неидеально для приложений, которые всё чаще распространяются в виде одного исполняемого файла.

Чтобы сделать приложение полностью самодостаточным в виде одного исполняемого файла, вы можете включить Embed PCK в параметрах пресета экспорта. Это встроит данные PCK в исполняемый файл, так что приложение можно будет перемещать без сбоев. Это также позволяет запускать приложение непосредственно из ZIP-архива без предварительной распаковки.

Примечание

Встраивание PCK имеет ограничение по размеру, зависящее от платформы. Очень большие приложения (несколько ГБ) могут не иметь возможности использовать эту функцию на всех платформах. Для получения более подробной информации обратитесь к документации по экспорту для целевой платформы.

Создание переносимых приложений

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

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

var config_path = OS.get_executable_path().get_base_dir().path_join("config.ini")
# Then use `config_path` to save/load configuration files using ConfigFile or similar.

Возможно, вы захотите сделать переносимый режим необязательным, поскольку он не всегда желателен. Обычно это реализуется путём обнаружения наличия определённого файла в папке с исполняемым файлом (например, файла с именем portable.txt) и использования папки с исполняемым файлом для конфигурации только при наличии этого файла.

Предупреждение

Помните, что это будет работать только в том случае, если приложение распаковано в место с возможностью записи. Это приведёт к ошибкам прав доступа, если исполняемый файл запускается из места, доступного только для чтения, например C:\Program Files в Windows.

Создание установщиков

Хотя игры обычно устанавливаются через лаунчеры, такие как Steam, или загружаются в виде ZIP-архива, приложения часто распространяются в виде установщиков для лучшей интеграции с рабочим столом. Установщик может выполнять такие действия, как добавление ярлыков в меню «Пуск» или на рабочий стол, настройка ассоциаций файлов и многое другое. Установщики также можно запускать автоматически через командную строку, что делает их более предпочтительными в корпоративной среде.

Godot не имеет встроенной поддержки создания установщиков для экспортированных проектов. Однако вы всё равно можете создавать свои собственные установщики с помощью сторонних инструментов.

Вот неполный список инструментов, которые можно использовать для создания установщиков:

  • Windows: Inno Setup, NSIS

    • Если у вас есть сертификат для подписи кода, не забудьте подписать и установщик, и исполняемый файл проекта. Для этого подпишите экспортированный исполняемый файл проекта, создайте установщик, содержащий экспортированный проект, затем вручную подпишите только что созданный установщик.

  • macOS: create-dmg

  • Linux: Flatpak

    • Существует Godot BaseApp, который можно использовать в качестве основы для создания пакетов Flatpak для проектов Godot. См. Flatpak Pixelorama в качестве примера Flatpak, использующего этот BaseApp.

Ресурсы

На этих страницах описаны задачи, обычно выполняемые в неигровых приложениях: