インスタンスの作成

注釈

このチュートリアルは、エディタ内でのシーンのインスタンス化について説明しています。コードからシーンをインスタンス化する方法については、 ノードとシーンインスタンス を参照してください。

以下に説明するGodotの インスタンシング のアプローチは、大量の類似オブジェクトを迅速にレンダリングするために使用できるハードウェアインスタンシングと混同しないでください。代わりに MultiMeshを使用した最適化 を参照してください。

前のパートでは、シーンとは1つのノードをルートとし、ツリー構造で構成されたノードの集まりであることを見てきました。プロジェクトは、いくつものシーンに分割することができます。この機能により、ゲームの様々なコンポーネントを分解して整理することができます。

好きなだけシーンを作成し「テキストシーン」を意味する .tscn 拡張子のファイルとして保存できます。前のレッスンの Label.tscn ファイルはその例です。シーンのコンテンツに関する情報をパックしているため、これらのファイルを "Packed Scenes" と呼んでいます。

以下はボールの例です。ボールが落ちたり壁で跳ねたりできるようにするために、Ballという名前の RigidBody2D ノードをルートとしており、さらに Sprite2D ノードと CollisionShape2D から構成されています。

../../_images/instancing_ball_scene.webp

一度保存したシーンは設計図として機能し、他のシーンで何度でも再利用することができます。このようにテンプレートからオブジェクトを複製することを、インスタンス化 (instancing) と呼びます。

../../_images/instancing_ball_instances_example.webp

前のパートで述べたように、インスタンス化されたシーンは、ノードのように動作します。エディタは、デフォルトでそのコンテンツを隠蔽します。Ballをインスタンス化すると、Ballノードだけが表示されます。また、各複製がユニークな名前を持っていることに注意してください。

Ball シーンのすべてのインスタンスは、ball.tscnと同じ構造とプロパティで開始されます。ただし、それぞれを独立して変更することができます。たとえば、跳ね返り方、重さ、またはソースシーンによって公開されるプロパティなどです。

実際に使う

インスタンス化を実際に使って、Godotで具体的にどう動くのかを見てみましょう。私たちが用意したボールのサンプルプロジェクトをダウンロードしてください: instancing_starter.zip

アーカイブをあなたのコンピュータ上で展開してください。インポートするためにはプロジェクトマネージャーが必要です。プロジェクトマネージャーにはGodotを開くことによってアクセスします。もしくはすでにGodotを開いているのであれば、 プロジェクト -> 終了してプロジェクト一覧を開く (Ctrl + Shift + Q, macOSでは Ctrl + Option + Cmd + Q ) をクリックしてください

プロジェクトマネージャーにて、インポート ボタンを使用してこのプロジェクトをインポートしてください。

../../_images/instancing_import_button.webp

表示されたポップアップで展開したフォルダに移動し、 project.godot ファイルをダブルクリックして開きます。

../../_images/instancing_import_project_file.webp

最後に、「インポートと編集」("Import & Edit")ボタンをクリックします。

../../_images/instancing_import_and_edit_button.webp

プロジェクトが古いGodotバージョンで最後に開かれたことを通知するウィンドウが表示される場合がありますが、それは問題ではありません。プロジェクトを開くには「OK」をクリックしてください。

このプロジェクトには、2つのパックされたシーンが含まれています。main.tscn(ボールと衝突する壁を含む)とball.tscnのシーンです。メインシーンは自動的に開きます。もし、メインシーンの代わりに空の3Dシーンが表示されたら、画面上部の2Dボタンを押してください。

../../_images/instancing_2d_scene_select.webp ../../_images/instancing_main_scene.webp

Mainノードの子として、ボールを追加してみましょう。Scene ドックで、Main ノードを選択します。次に、シーンドックの上部にあるリンクアイコンをクリックします。このボタンで、現在選択されているノードの子として、シーンのインスタンスを追加することができます。

../../_images/instancing_scene_link_button.webp

Ballシーンをダブルクリックしてインスタンス化します。

../../_images/instancing_instance_child_window.webp

ビューポートの左上隅にボールが表示されます。

../../_images/instancing_ball_instanced.webp

それをクリックし、ビューの中心に向かってドラッグします。

../../_images/instancing_ball_moved.webp

F5キー(macOSでは Cmd + B) を押してゲームを実行してください。ボールが落ちるのが見えるはずです。

さて、Ball ノードのインスタンスをさらに作成したいと思います。ボールを選択したまま、 Ctrl-D (macOS では Cmd-D) を押して、複製コマンドを呼び出します。クリックアンドドラッグして、新しいボールを別の場所に移動してください。

../../_images/instancing_ball_duplicated.webp

この作業を、シーン内にいくつかボールができるまで繰り返すことができます。

../../_images/instancing_main_scene_with_balls.webp

もう一度ゲームを実行します。今度は、すべてのボールが互いに独立して落下するのが見えるはずです。これがインスタンスの役割です。それぞれが、テンプレートのシーンを独立して再現しているのです。

シーンとインスタンスの編集

インスタンスの機能はもっとあります。次のようなことができます:

  1. インスペクタを使って、1つのボールのプロパティを他のボールに影響を与えずに変更します。

  2. ball.tscnシーンを開き、Ball ノードに変更を加えることによって、すべての Ball のデフォルトプロパティを変更することができます。保存すると、プロジェクト内のすべてのBallインスタンスの値が更新されます。

注釈

インスタンスのプロパティを変更すると、対応するパックされたシーンの値が常に上書きされます。

試してみましょう。FileSystem の ball.tscn をダブルクリックして開きます。

../../_images/instancing_ball_scene_open.webp

左側のシーン ドックで、Ball ノードを選択します。次に、右側のインスペクターで、PhysicsMaterial プロパティをクリックして展開します。

../../_images/instancing_physics_material_expand.webp

Bounce プロパティの数値フィールドをクリックして、0.5と入力し、 Enter を押して、Bounce プロパティを 0.5にセットしてください。

../../_images/instancing_property_bounce_updated.webp

F5 を押してゲームを実行します。すべてのボールがよりバウンドするようになったことに注目してください。ボールのシーンはすべてのインスタンスのテンプレートなので、これを修正して保存すると、すべてのインスタンスがそれに応じて更新されます。

それでは、個々のインスタンスを調整しましょう。ビューポートの上にある対応するタブをクリックして、Mainシーンに戻りましょう。

../../_images/instancing_scene_tabs.webp

インスタンス化されたBallノードの1つを選択し、インスペクタで、その重力スケール("Gravity Scale")値を10に設定します。

../../_images/instancing_property_gravity_scale.png

変更したプロパティの横に、グレーの「復元」ボタンが表示されます。

../../_images/instancing_property_revert_icon.png

このアイコンは、元のパックされたシーンから値を上書きしていることを示します。元のシーンでプロパティを変更しても、値のオーバーライドはインスタンスに保存されます。復元アイコンをクリックすると、プロパティが保存されたシーンの値に復元されます。

ゲームを再実行し、このボールが他のボールよりずっと速く落ちていることに注目してください。

注釈

1つのボールだけの PhysicsMaterial の値を変更できないことに気が付いたかもしれません。これは、 PhysicsMaterial がリソースであり、元のシーンにリンクしている他のシーン内で変更するにはユニーク化されている必要があるからです。リソースを1つのインスタンスに固有にするには、インスペクタで Physics Material プロパティを右クリックし、コンテキストメニューの「ユニーク化」をクリックします。

リソースは、後のレッスンで取り上げますが、Godotゲームの重要な構成要素の一つです。

デザイン言語としてのシーンインスタンス

Godotのインスタンスとシーンは、優れたデザイン言語を提供し、他のエンジンとは一線を画しています。私たちは、一からこのコンセプトに基づいてGodotを設計しました。

Godot でゲームを作る場合、MVC (Model-View-Controller) や Entity-Relationship ダイアグラムのようなアーキテクチャのコードパターンを排除することをお勧めします。その代わりに、プレイヤーがゲームの中で目にする要素を想像することから始め、それらに基づいてコードを構成するとよいでしょう。

例えば、シューティングゲームを分解すると、こんな感じです。

../../_images/instancing_diagram_shooter.png

You can come up with a diagram like this for almost any type of game. Each rectangle represents an entity that's visible in the game from the player's perspective. The arrows point towards the instantiator of each scene.

ダイアグラムができたら、そこに記載されている各要素のシーンを作成して、ゲームを開発することをお勧めします。シーンのツリーを構築するために、コードまたはエディタで直接インスタンス化を使用するのがよいでしょう。

プログラマーは、抽象的なアーキテクチャを設計し、そこにコンポーネントを当てはめようとすることに多くの時間を費やす傾向があります。シーンをベースにした設計は、開発をより速く、より簡単にし、ゲームロジックそのものに集中することができます。ほとんどのゲームコンポーネントはシーンに直接マッピングされるため、シーンのインスタンス化をベースにしたデザインを使用すると、他のアーキテクチャのコードはほとんど必要ありません。

ここでは、大量のアセットとネストされた要素を持つオープンワールドゲームのシーン図の例を示します。

../../_images/instancing_diagram_open_world.png

まず、部屋を作るところから始めると想像してください。家具をユニークに配置した、いくつかの異なる部屋のシーンを作成することができます。その後、インテリアに複数の部屋のインスタンスを使用する家のシーンを作成することができます。インスタンス化された多くの家と、城塞を置くための大きな地形から、城塞を作ることになります。これらは、それぞれ1つまたは複数のサブシーンをインスタンス化したシーンとなります。

その後、衛兵のシーンを作り、城塞に追加することもできます。間接的にゲームの世界全体に追加されることになります。

Godotでは、このようにシーンを作成してインスタンス化するだけで、簡単にゲーム上で反復することができます。エディターは、プログラマー、デザイナー、アーティストが同様に利用できるように設計されています。典型的なチーム開発では、2Dや3Dのアーティスト、レベルデザイナー、ゲームデザイナー、アニメーターが参加し、全員がGodotエディターで作業を行います。

要約

インスタンス化とは、設計図からオブジェクトを生成するプロセスで、多くの便利な使い方があります。シーンを使えば、次のようなことが実現できます。

  • ゲームを再利用可能なコンポーネントに分割する機能。

  • 複雑なシステムを構造化し、カプセル化するためのツール。

  • ゲームプロジェクトの構造を自然な方法で考えるための言語。