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.
Checking the stable version of the documentation...
Використання Дерева сцени
Вступ
У попередніх уроках все оберталося навколо концепції вузлів. Сцени - це колекції вузлів. Вони стають активними, як тільки входять у дерево сцен.
MainLoop (Головний цикл)
Внутрішня робота Godot полягає в наступному. Існує клас OS, який є єдиним екземпляром, який запускається на початку. Після цього завантажуються всі драйвери, сервери, скриптові мови, система сцен тощо.
Коли ініціалізація завершена, OS потрібно для запуску MainLoop. До цього моменту все це внутрішня обробка (ви можете перевірити файл main/main.cpp у вихідному коді, якщо вам стане колись цікаво побачити, як це працює всередині).
Програма користувача, або гра, запускається в MainLoop. У цьому класі є кілька методів для ініціалізації, простою (зворотний синхронізований кадр), фіксації (фізичний синхронізований зворотний виклик) та введення. Однак це низький рівень, і при розробці ігор в Godot, рідко має сенс писати власний MainLoop.
Дерево Сцен
Один із способів пояснити, як працює Godot, полягає в тому, що це високорівневий ігровий движок над низькорівневим проміжним програмним забезпеченням.
Система сцени — це ігровий механізм, тоді як OS і сервери — низькорівневий API.
Система сцен забезпечує власний головний цикл для ОС, SceneTree. Він автоматично встановлюється і налаштовується під час запуску сцени, не потрібно робити зайвих робіт.
Важливо знати, про наявність цього класу, оскільки він має кілька важливих застосувань:
Він містить кореневий Viewport, до якого додається сцена в якості нащадка, при першому відкритті, щоб стати частиною Дерева сцен (докладніше про це далі).
Він містить інформацію про групи і має засоби для виклику всіх вузлів групи, або отримання їх списку.
Він містить деяку функціональність глобального стану, наприклад встановлення режиму паузи, або вихід.
Коли вузол є частиною дерева сцен, сиглтон (одиночний екземпляр) SceneTree можна отримати, викликавши Node.get_tree().
Кореневе вікно перегляду
Кореневе Viewport (Вікно перегляду) завжди знаходиться у верхній частині сцени. З вузла його можна отримати двома різними способами:
get_tree().root # Access via scene main loop.
get_node("/root") # Access via absolute path.
GetTree().Root // Access via scene main loop.
GetNode("/root"); // Access via absolute path.
Цей вузол містить головне вікно перегляду. Всі нащадки Viewport, малюються всередині нього за замовчуванням, тому є сенс в тому, щоб коренем всіх вузлів завжди був вузол такого типу, інакше нічого не буде видно.
Хоча в сцені можуть створюватися інші вікна перегляду (для ефектів розділеного екрана і подібних речей), це єдине, яке ніколи не створюється користувачем. Воно створюється автоматично всередині SceneTree (дерева сцен).
Дерево сцени
Коли вузол підключений безпосередньо, або опосередковано, до кореневого вікна перегляду, він стає частиною дерева сцен.
Це означає, що, як пояснювалося в попередніх посібниках, він отримає зворотні виклики _enter_tree() і _ready() (а також _exit_tree()).
Коли вузли потрапляють до дерева сцен, вони стають активними. Вони отримують доступ до всього, що їм потрібно для обробки, отримання вхідних даних, відображення 2D та 3D візуальних елементів, отримання та надсилання сповіщень, відтворення звуків тощо. Коли їх видаляють з дерева сцен, вони втрачають ці можливості.
Послідовність в дереві
Більшість операцій із вузлами в Godot, таких як малювання 2D, обробка чи отримання сповіщень, виконуються в деревоподібному порядку або зверху вниз, як це видно в редакторі (також відомий як обхід попереднього замовлення):
Наприклад, для верхнього вузла сцени спочатку викликається функція _process(), потім для вузла під ним викликається функція _process(), потім вузол під ним і так далі.
Важливим винятком є функція _ready(): кожен батьківський вузол має свою функцію _ready(), що викликається лише після того, як усі його дочірні вузли викликають свої функції _ready(), так що батьківський вузол знає, що його діти повністю готові до доступу. Це також відомо як обхід після замовлення. На наведеному вище зображенні NameLabel сповіщатиметься першим (але лише після своїх дочірніх елементів, якщо вони були!), потім Name тощо, а Panel буде сповіщено останнім.
Порядок операцій також можна змінити за допомогою властивості вузла process_priority. Вузли з меншим номером викликаються першими. Наприклад, вузли з пріоритетами "0, 1, 2, 3" будуть викликані в такому порядку зліва направо.
"Становлення активним" при вході в дерево сцен
Сцена завантажується з диска, або створюється скриптом.
Кореневий вузол цієї сцени (лише один корінь, пам’ятаєте?) додається або як дочірній елемент «кореневого» вікна перегляду (з SceneTree), або до будь-якого з його нащадків.
Кожен вузол щойно доданої сцени отримає сповіщення "enter_tree" ( зворотний виклик
_enter_tree()у GDScript) у порядку зверху вниз (обхід попереднього замовлення).Кожен вузол отримає сповіщення «готовий» ( зворотний виклик
_ready()у GDScript) для зручності, щойно всі його дочірні вузли отримають сповіщення «готовий» (обхід після замовлення).Коли сцену (або її частину) видалено, вони отримують сповіщення про "вихід зі сцени" (зворотний виклик
_exit_tree()у GDScript) у порядку знизу-вгору (зворотному порядку зверху-вниз).
Зміна поточної сцени
Після завантаження сцени ви можете змінити цю сцену на іншу. Один із способів зробити це — використати функцію SceneTree.change_scene_to_file():
func _my_level_was_completed():
get_tree().change_scene_to_file("res://levels/level2.tscn")
public void _MyLevelWasCompleted()
{
GetTree().ChangeSceneToFile("res://levels/level2.tscn");
}
Замість використання шляхів до файлів можна також використовувати готові ресурси PackedScene за допомогою еквівалентної функції SceneTree.change_scene_to_packed(PackedScene scene):
var next_scene = preload("res://levels/level2.tscn")
func _my_level_was_completed():
get_tree().change_scene_to_packed(next_scene)
public void _MyLevelWasCompleted()
{
var nextScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
GetTree().ChangeSceneToPacked(nextScene);
}
Це швидкі та корисні способи перемикання сцен, але мають недолік, що гра зупинятиметься, доки нова сцена не буде завантажена та запущена. На певному етапі розробки вашої гри може бути краще створити відповідні екрани завантаження з індикатором прогресу, анімованими індикаторами або потоковим (фоновим) завантаженням. Це потрібно зробити вручну за допомогою Синглтони (автозавантаження) і Тло завантаження.