Up to date

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

Použití SceneTree

Úvod

V předchozích výukových kurzech se vše točilo kolem konceptu uzlů. Scény jsou kolekce uzlů. Ty se stávají aktivními, jakmile vstoupí do stromu scén (scene tree).

MainLoop

Godot funguje interně následujícím způsobem. Existuje třída OS, pouze její instance běží uplně od začátku. Poté se načtou všechny ovladače, servery, skriptovací jazyky, systém scén atd.

Po dokončení inicializace potřebuje OS dodat ke spuštění MainLoop . Až do této chvíle vše funguje uvnitř enginu (můžete se podívat do souboru main/main.cpp ve zdrojovém kódu, pokud vás někdy bude zajímat, jak to vlastně běhá).

Uživatelský program nebo hra se spustí pomocí MainLoop. Tato třída má několik metod pro inicializaci, nečinnost (funkce synchronizované se snímky), pravidelně se opakující (funkce synchronizované s fyzikou) a vstup. Opět se jedná o záležitost enginu a při tvorbě her v Godotu má psaní vlastní MainLoop málokdy smysl.

Strom scény

Fungování Godot lze vysvětlit i tak, že se jedná o vysokoúrovňový herní engine nad nízkoúrovňovým middlewarem.

Systém scén je herní engine, zatímco OS a servery představují nízkoúrovňové API.

Systém scén poskytuje OS vlastní hlavní smyčku, SceneTree. Ta se automaticky vytváří a nastavuje při spuštění scény, není třeba dělat nic dalšího.

Je důležité vědět, že tato třída existuje, protože má několik důležitých použití:

  • Obsahuje kořenový Viewport(výřez), do kterého je scéna přidána jako potomek při svém prvním otevření, aby se stala součástí Stromu scén (Scene Tree) (o tom více příště).

  • Obsahuje informace o skupinách a umožňuje zavolat všechny uzly ve skupině nebo získat jejich seznam.

  • Obsahuje některé funkce pro změnu globálního stavu, jako je nastavení režimu pozastavení nebo ukončení procesu.

Pokud je uzel(Node) součástí Scene Tree, lze singleton SceneTree získat voláním Node.get_tree().

Kořenový výřez (viewport)

Kořenový Viewport je vždy na vrcholu scény. Z aktuálního uzlu jej lze získat dvěma různými způsoby:

get_tree().root # Access via scene main loop.
get_node("/root") # Access via absolute path.

Tento uzel obsahuje hlavní průzor (výřez). Vše, co je potomkem Viewport, se ve výchozím nastavení uvnitř něho vykresluje, takže dává smysl, že vrcholem všech uzlů je vždy uzel tohoto typu, jinak by nebylo nic vidět.

Ačkoli ve scéně lze vytvářet další výřezy (pro efekty rozdělené obrazovky apod.), tento výřez je jediný, který nevytváří nikdy uživatel . Vzniká automaticky uvnitř stromu SceneTree.

Strom scény

Pokud je uzel přímo nebo nepřímo připojen ke kořenovému výřezu, stává se součástí stromu scény.

To znamená, že jak bylo vysvětleno v předchozích tutoriálech, získá funkce _enter_tree() a _ready() (a také _exit_tree()).

../../_images/activescene.webp

Když uzly vstoupí do SceneTree, stanou se aktivními. Získají přístup ke všemu, co potřebují ke správné funkci, získávají vstupy, zobrazují 2D a 3D vizualizace, přijímají a odesílají oznámení, přehrávají zvuky atd. Když jsou ze stromu scény odstraněny, tyto schopnosti ztrácejí.

Pořadí ve stromu

Most node operations in Godot, such as drawing 2D, processing, or getting notifications are done in tree order, or top to bottom as seen in the editor (also known as pre-order traversal):

../../_images/toptobottom.webp

For example, the top node in a scene has its _process() function called first, then the node below it has its _process() function called, then the node below that and so on.

An important exception is the _ready() function: each parent node has its _ready() function called only after all its child nodes have their _ready() functions called, so that the parent knows its children are completely ready to be accessed. This is also known as post-order traversal. In the above image, NameLabel would be notified first (but only after its children, if it had any!), followed by Name, etc., and Panel would be notified last.

The order of operations can also be overridden using the process_priority node property. Nodes with a lower number are called first. For example, nodes with the priorities "0, 1, 2, 3" would be called in that order from left to right.

"Aktivování" vstupem do SceneTree

  1. Scéna je načtena z disku nebo vytvořena pomocí skriptů.

  2. The root node of that scene (only one root, remember?) is added as either a child of the "root" Viewport (from SceneTree), or to any of its descendants.

  3. Every node of the newly added scene will receive the "enter_tree" notification ( _enter_tree() callback in GDScript) in top-to-bottom order (pre-order traversal).

  4. Every node will receive the "ready" notification ( _ready() callback in GDScript) for convenience, once all its children have received the "ready" notification (post-order traversal).

  5. When a scene (or part of it) is removed, they receive the "exit scene" notification ( _exit_tree() callback in GDScript) in bottom-to-top order (the exact reverse of top-to-bottom order).

Změna aktuální scény

After a scene is loaded, you may want to change this scene for another one. One way to do this is to use the SceneTree.change_scene_to_file() function:

func _my_level_was_completed():
    get_tree().change_scene_to_file("res://levels/level2.tscn")

Rather than using file paths, one can also use ready-made PackedScene resources using the equivalent function 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)

These are quick and useful ways to switch scenes but have the drawback that the game will stall until the new scene is loaded and running. At some point in the development of your game, it may be preferable to create proper loading screens with progress bar, animated indicators or threaded (background) loading. This must be done manually using Singletons (Autoload) and Background loading.