Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Автозагрузки по сравнению с обычными узлами

Godot предлагает функцию автоматической загрузки узлов в корень проекта, позволяющую получить к ним глобальный доступ, которые могут выполнять роль синглтонов: Singletons (Autoload). Эти узлы автозагрузки не освобождаются при изменении сцены из кода с помощью SceneTree.change_scene_to_file.

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

Проблема с прерыванием звука

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

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

Решением является создание глобального, автозагружаемого класса менеджера звуковых эффектов. Он генерирует пул узлов AudioStreamPlayer, которые циклически перебираются при каждом новом запросе на звуковые эффекты. Назовем этот класс Sound, и вы сможете использовать его из любого места проекта, вызвав Sound.play("coin_pickup.ogg"). Это решает проблему в краткосрочной перспективе, но порождает дополнительные проблемы:

  1. Глобальное состояние: теперь один объект отвечает за данные всех объектов. Если в классе Sound есть ошибки или отсутствует AudioStreamPlayer, то все вызывающие его узлы могут сломаться.

  2. Глобальный доступ: теперь, когда любой объект может вызвать Sound.play(sound_path) откуда угодно, более нет простого способа найти источник ошибки.

  3. Глобальное распределение ресурсов: с пулом узлов AudioStreamPlayer, хранящихся с самого начала, вы можете либо иметь слишком мало и сталкиваются с ошибками, или слишком много и использовать больше памяти, чем вам нужно.

Примечание

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

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

Сравните это с тем, что каждая сцена содержит столько узлов AudioStreamPlayer, сколько нужно внутри себя, и все эти проблемы исчезнут:

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

  2. Каждая сцена получает доступ только к своим узлам. Теперь, если есть ошибка, легко найти, какой из узлов виноват.

  3. Каждая сцена выделяет именно то количество ресурсов, которое ей необходимо.

Управление общей функциональностью или данными

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

В случае с функциями можно создать новый тип Node, который обеспечивает эту функцию для отдельной сцены, используя ключевое слово class_name в GDScript.

Когда дело доходит до данных, вы можете:

  1. Создайте новый тип Resource для совместного использования данных.

  2. Храните данные в объекте, к которому имеет доступ каждый узел, например, используя свойство owner для доступа к корневому узлу сцены.

Когда вы должны использовать Autoload (автозагрузку)

GDScript поддерживает создание статических функций с помощью static func. В сочетании с class_name это позволяет создавать библиотеки вспомогательных функций без необходимости создавать экземпляр для их вызова. Ограничением статических функций является то, что они не могут ссылаться на переменные-члены, нестатические функции или self.

Начиная с версии Godot 4.1, GDScript также поддерживает статические переменные с помощью static var. Это означает, что теперь можно совместно использовать переменные для всех экземпляров класса без необходимости создавать отдельную автозагрузку.

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

Примечание

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

В результате вы можете получить узел автозагрузки, например, автозагрузку с именем Sound, можно, вызвав get_node("/root/Sound").