シーンツリー

はじめに

これまでのチュートリアルは、すべてがノードの概念を中心に展開していました。シーンはノードのコレクションです。それら シーンツリー に入るとアクティブになります。

メインループ

Godotの内部的な働きは次のとおりです。OSクラスがあります。これは最初に実行される唯一のインスタンスです。その後、すべてのドライバ、サーバ、スクリプト言語、シーンシステムなどがロードされます。

初期化が完了したら、実行するためにOSにメインループを提供する必要があります。これまでのところはすべて内部の作業です(これが内部でどのように機能するかを知りたい場合は、ソースコードのmain/main.cppファイルを確認できます)。

ユーザー プログラムまたはゲームは、MainLoopで起動します。このクラスには、初期化、アイドル (フレーム同期コールバック)、固定 (物理同期コールバック)、および入力のためのいくつかのメソッドがあります。繰り返しますが、これは低レベルの処理であり、Godotでゲームを作るときに、独自にMainLoopを書くことはめったに意味がありません。

シーンツリー

Godotの仕組みを説明する方法の1つは、Godotが低レベルのミドルウェアよりも高レベルなゲームエンジンであることです。

シーンシステムはゲームエンジンで、OSとサーバーは低レベルのAPIです。

シーンシステムは、OSに独自のメインループSceneTreeを提供します。これは自動的にインスタンス化され、シーンの実行時に設定されるので、余分な作業を行う必要はありません。

このクラスにはいくつかの重要な用途があるため、このクラスが存在することを知っておくことが重要です:

  • ルートViewportが含まれており、最初に開かれたときに、 シーン ツリー の一部になるためにシーンが子として追加されます(詳細は次のページを参照)。
  • それにはグループに関する情報が含まれており、グループ内のすべてのノードを呼び出すか、それらのリストを取得する手段があります。
  • これには、一時停止モードの設定やプロセスの終了など、いくつかのグローバル状態に関する機能が含まれています。

ノードがシーンツリーの一部である場合、 Node.get_tree() を呼び出すことで SceneTree シングルトンを取得できます。

ルートビューポート

ルートViewportは常にシーンの一番上にあります。ノードからは、次の2つの方法で取得できます:

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ビジュアルの表示、通知の送受信、サウンドの再生などに必要なすべてのものにアクセスできます。 シーンツリー から削除されると、これらの機能を失います。

ツリーの順序

2Dの描画、処理、通知の取得など、Godotのほとんどのノード操作はツリー順に実行されます。これは、現在のノードのより前に、ツリー順序の低いランクを持つ親と兄弟が通知を取得することを意味します。

../../_images/toptobottom.png

シーンツリー に入って「アクティブになる」

  1. シーンはディスクから読み込まれるか、スクリプトによって作成されます。
  2. そのシーンのルートノードは(ルートは 1 つだけです、覚えていますか?)、「ルート」ビューポートの子として(シーンツリーから)、またはその任意の子や孫に追加されます。
  3. 新しく追加されたシーンのすべてのノードは、GDScript で 「enter_tree」 通知(_enter_tree() コールバック)を上から下の順に受け取ります。
  4. ノードとそのすべての子がアクティブシーン内にあるときには、追加の通知、 「ready」(GDScriptでの_ready()コールバック)が便宜上提供されています。
  5. シーン(またはその一部)が削除されると、GDScriptで 「終了シーン」通知(_exit_tree()コールバック)が一番下から上の順序で受け取ります

現在のシーンの変更

シーンがロードされた後、このシーンを別のシーンに変更することがしばしば望まれます。これを行う簡単な方法は、 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");
}

ファイルパスを使用する代わりに、同等の関数 SceneTree.change_scene_to(PackedScene scene) を使用して、既製の PackedScene リソースを使用することもできます。

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);
}

これらは、シーンを切り替える迅速で便利な方法ですが、新しいシーンが読み込まれて実行されるまでゲームが停止するという欠点があります。ゲーム開発のある時点で、プログレスバー、アニメーション インジケータ、またはスレッド (バックグラウンド) での読み込みを備えた、適切な読み込み画面を作成することをお勧めします。これについては、自動読み込み(次の章を参照)と バックグラウンド読み込み を使用して手動で行う必要があります。