Дерево сцени

Вступ

У попередніх уроках все оберталося навколо концепції вузлів. Сцени - це колекції вузлів. Вони стають активними, як тільки входять у дерево сцен.

MainLoop (Головний цикл)

Внутрішня робота Godot полягає в наступному. Існує клас OS, який є єдиним екземпляром, який запускається на початку. Після цього завантажуються всі драйвери, сервери, скриптові мови, система сцен тощо.

Коли ініціалізація завершена, OS потрібно для запуску MainLoop. До цього моменту все це внутрішня обробка (ви можете перевірити файл main/main.cpp у вихідному коді, якщо вам стане колись цікаво побачити, як це працює всередині).

Програма користувача, або гра, запускається в MainLoop. У цьому класі є кілька методів для ініціалізації, простою (зворотний синхронізований кадр), фіксації (фізичний синхронізований зворотний виклик) та введення. Однак це низький рівень, і при розробці ігор в Godot, рідко має сенс писати власний MainLoop.

Дерево сцени

Суть роботи Godot полягає в тому, що це ігровий движок високого рівня заснований на програмному забезпеченні низького рівня.

Система сцен - це ігровий движок, тоді як OS і сервери - API низького рівня.

Система сцен забезпечує власний головний цикл для ОС, SceneTree. Він автоматично встановлюється і налаштовується під час запуску сцени, не потрібно робити зайвих робіт.

Важливо знати, про наявність цього класу, оскільки він має кілька важливих застосувань:

  • Він містить кореневий Viewport, до якого додається сцена в якості нащадка, при першому відкритті, щоб стати частиною Дерева сцен (докладніше про це далі).

  • Він містить інформацію про групи і має засоби для виклику всіх вузлів групи, або отримання їх списку.

  • Він містить деяку функціональність глобального стану, наприклад встановлення режиму паузи, або вихід.

Коли вузол є частиною дерева сцен, сиглтон (одиночний екземпляр) SceneTree можна отримати, викликавши Node.get_tree().

Кореневе вікно перегляду

Кореневе Viewport (Вікно перегляду) завжди знаходиться у верхній частині сцени. З вузла його можна отримати двома різними способами:

get_tree().get_root() # Access via scene main loop.
get_node("/root") # Access via absolute path.
GetTree().GetRoot(); // Access via scene main loop.
GetNode("/root"); // Access via absolute path.

Цей вузол містить головне вікно перегляду. Всі нащадки Viewport, малюються всередині нього за замовчуванням, тому є сенс в тому, щоб коренем всіх вузлів завжди був вузол такого типу, інакше нічого не буде видно.

Хоча в сцені можуть створюватися інші вікна перегляду (для ефектів розділеного екрана і подібних речей), це єдине, яке ніколи не створюється користувачем. Воно створюється автоматично всередині SceneTree (дерева сцен).

Дерево сцени

Коли вузол підключений безпосередньо, або опосередковано, до кореневого вікна перегляду, він стає частиною дерева сцен.

Це означає, що, як пояснено в попередніх уроках, він отримає зворотні виклики _enter_tree () і _ready() (а також _exit_tree()).

../../_images/activescene.png

Коли вузли входять у дерево сцен, вони стають активними. Вони отримують доступ до всього необхідного для обробки, отримують введення, демонструють 2D та 3D-візуальні зображення, отримують та надсилають сповіщення, відтворюють звуки тощо. Коли їх видаляють із дерева сцен , вони втрачають ці здібності.

Послідовність в дереві

Більшість операцій з вузлами в Godot, такі як малювання 2D, обробка, або отримання сповіщень, виконуються в послідовності дерева. Це означає, що предки та побратими з нижчим рангом у послідовності (по дереву) отримуватимуть повідомлення перед поточним вузлом.

../../_images/toptobottom.png

"Становлення активним" при вході в дерево сцен

  1. Сцена завантажується з диска, або створюється скриптом.

  2. Кореневий вузол цієї сцени (лише один корінь, пам'ятаєте?) додається як нащадок «кореня» Viewport (з SceneTree), або будь-якому його нащадку, чи нащадку нащадка.

  3. Кожен вузол щойно доданої сцени отримає сповіщення "enter_tree" (зворотний виклик _enter_tree () у GDScript) у порядку зверху до низу.

  4. Для зручності передбачено додаткове сповіщення, "ready" (зворотний виклик (_ready () в GDScript), коли вузол та всі його нащадки знаходяться всередині активної сцени.

  5. Коли сцена (або її частина) видаляється, вони отримують сповіщення "exit scene" (зворотний виклик _exit_tree () у GDScript) у порядку "знизу до верху"

Зміна поточної сцени

Після завантаження сцени часто бажано змінити цю сцену на іншу. Простий спосіб зробити це - використати функцію SceneTree.change_scene():

func _my_level_was_completed():
    get_tree().change_scene("res://levels/level2.tscn")
public void _MyLevelWasCompleted()
{
    GetTree().ChangeScene("res://levels/level2.tscn");
}

Замість використання шляхів до файлів можна також використовувати готові ресурси PackedScene, використовуючи еквівалентну функцію SceneTree.change_scene_to(PackedScene scene):

var next_scene = preload("res://levels/level2.tscn")

func _my_level_was_completed():
    get_tree().change_scene_to(next_scene)
public void _MyLevelWasCompleted()
{
    var nextScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
    GetTree().ChangeSceneTo(nextScene);
}

Це швидкі та корисні способи переключення сцен, але мають той недолік, що гра буде зупинятися для завантаження та запуску нової сцени. У якийсь момент розробки гри ви можете задуматися над створенням належних екранів завантаження з панеллю прогресу, анімованими індикаторами, або завантаженням фону. Це потрібно зробити вручну за допомогою автозавантажень (див. Наступний розділ) та Background loading.