シーンツリーの使用
はじめに
これまでのチュートリアルは、すべてがノードの概念を中心に展開していました。シーンはノードのコレクションです。それら シーンツリー に入るとアクティブになります。
メインループ
Godotの内部的な働きは次のとおりです。OSクラスがあります。これは最初に実行される唯一のインスタンスです。その後、すべてのドライバ、サーバ、スクリプト言語、シーンシステムなどがロードされます。
初期化が完了したら、実行するためにOSにメインループを提供する必要があります。これまでのところはすべて内部の作業です(これが内部でどのように機能するかを知りたい場合は、ソースコードのmain/main.cppファイルを確認できます)。
ユーザー プログラムまたはゲームは、MainLoopで起動します。このクラスには、初期化、アイドル (フレーム同期コールバック)、固定 (物理同期コールバック)、および入力のためのいくつかのメソッドがあります。繰り返しますが、これは低レベルの処理であり、Godotでゲームを作るときに、独自にMainLoopを書くことはめったに意味がありません。
シーンツリー
One of the ways to explain how Godot works is that it's a high-level game engine over a low-level middleware.
The scene system is the game engine, while the OS and servers are the low-level API.
シーンシステムは、OSに独自のメインループSceneTreeを提供します。これは自動的にインスタンス化され、シーンの実行時に設定されるので、余分な作業を行う必要はありません。
このクラスにはいくつかの重要な用途があるため、このクラスが存在することを知っておくことが重要です:
ルートViewportが含まれており、最初に開かれたときに、 シーン ツリー の一部になるためにシーンが子として追加されます(詳細は次のページを参照)。
それにはグループに関する情報が含まれており、グループ内のすべてのノードを呼び出すか、それらのリストを取得する手段があります。
これには、一時停止モードの設定やプロセスの終了など、いくつかのグローバル状態に関する機能が含まれています。
ノードがシーンツリーの一部である場合、 Node.get_tree() を呼び出すことで SceneTree シングルトンを取得できます。
ルートビューポート
ルートViewportは常にシーンの一番上にあります。ノードからは、次の2つの方法で取得できます:
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() 関数が呼び出され、続いてその下にあるノードで _process() が呼び出されます。
重要な例外は _ready() 関数です。各親ノードは、すべての子ノードが _ready() 関数を呼び出した後に、親ノードの _ready() 関数を呼び出します。これは親が子に対して完全にアクセスできる状態にあるということです。これはポストオーダートラバーサルとも呼ばれます。上の画像では NameLabel が最初に実行され (ただし子が存在する場合はその子の後に)、続いて Name などが続き、最後に Panel が実行されます。
実行の順序は process_priority ノードプロパティを使用してオーバーライドすることもできます。番号が小さいノードが最初に呼び出されます。たとえば優先度 "0, 1, 2, 3" を持つノードは、左から右の順序で呼び出されます。
*シーンツリー*に入ることで「アクティブになる」
シーンはディスクから読み込まれるか、スクリプトによって作成されます。
そのシーンのルートノードは(ルートは 1 つだけです、覚えていますか?)、(シーンツリーからの)「ルート」ビューポートの子として、またはその任意の子や孫に追加されます。
新しくシーンツリーに追加されたすべてのノードは、GDScript で "enter_tree"の 通知 (
_enter_tree()コールバック)を上から下の順に受け取ります。ノードの全ての子が "ready" 通知を受信すると (ポストオーダートラバーサル)、ノード自身が "ready" 通知 (GDScript の
_ready()コールバック) を受信します。シーン(またはその一部)が削除されると、GDScriptで "exit scene" 通知 (
_exit_tree()コールバック) が下から上の順序 (上から下の順序とは逆) で受け取ります)。
現在のシーンの変更
シーンがロードされた後、このシーンを別のシーンに変更することがしばしば望まれます。これを行う1つの方法は、 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");
}
ファイルパスを使用する代わりに、同等の関数 SceneTree.change_scene_to_packed(PackedScene scene) を使用して、既製の PackedScene リソースを使用することもできます。
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);
}
これらは、シーンを切り替える迅速で便利な方法ですが、新しいシーンが読み込まれて実行されるまでゲームが停止するという欠点があります。ゲーム開発のある時点で、プログレスバー、アニメーションインジケータ、またはスレッド (バックグラウンド) での読み込みを備えた、適切な読み込み画面を作成することをお勧めします。これについては、シングルトン (自動読み込み) と バックグラウンド読み込み を使用して手動で行う必要があります。