指定したタイプのすべてのエンティティを、プロジェクトを実行するときと同じ方法で動作するようにしたい(特定のイベントおよび条件が発生したときに同じアクションで応答するように設定したい)場合があります。たとえば、プレーヤーがコントロールするユニットが自分に十分近づいたら、ドアを開く、照明をオンにする、または敵を非友好的にするなどの設定が必要になることがあります。
この設定は、プロジェクト内の Lua モジュールおよびフロー グラフにエンティティを関連付ける「スクリプト コンポーネント」と「フロー コンポーネント」を使用することによって、簡単に行うことができます。これらの Lua モジュールおよびフロー グラフは、エンティティのライフタイム中に発生するイベントに応答して、エントリに適した応答を実行することができます。
これらのコンポーネントは、エンティティの動作を比較的自己完結型として保持できるので便利です。これにより、ゲームの管理や動作の再利用が容易になります。たとえば、レベル内の各ドアの状態をチェックするゲームのメインの更新ループ内に Lua ルーチンを含める代わりに、自動的に呼び出されるスクリプト コンポーネント内に、ドアのすべてのダイナミック ランタイム動作をカプセル化することができます。これで、メインのゲームプレイのスクリプトとフロー グラフが特定のタイプのゲーム オブジェクトの処理ロジックで乱雑にならないように維持するとともに、異なるエンティティ間(および複数のプロジェクト間)で動作をより簡単に共有できるようになります。
フローは、ユーザが簡単に使用して、プロトタイプをすばやく設定することができる視覚的な言語であるため、エンティティの動作を設定するのに適しています。
外部フロー エディタでエンティティのフロー グラフを作成する必要があります。
メイン メニューで Window > External Flow Editor を選択して、エディタを起動します。
フロー エディタを開いたら、File > New を選択して新しいグラフを開始します。
エンティティに必要な動作を使用して、新しいグラフを設定します。
外部フロー エディタは、ノードを追加および削除するためのコントローラが Unit Flow Eeditor と同じであり、これとまったく同じように機能します。レベル フローおよびユニット フローで使用できるのと同じノード セットを、グラフ内で使用できます。エンティティを扱う際に特に便利なノードもいくつかあります。以下の例を参照してください。
File > Save を選択してグラフを保存します。これにより、プロジェクト内に新しい .flow_editor リソースが作成されます。
次に、ドアを表すエンティティのフロー グラフの例を示します。このドアには、ロックされているかどうかを追跡するためのカスタム データ コンポーネントが使用されています。フレームごとに、ドアがロック解除されていてカメラが十分近い位置にある場合は、エンティティが所有するユニット上でアニメーションが再生されて、ドアが自動的に開きます。
このグラフでは、次に示すいくつかの便利な方法を示します。
Event > Entity Spawned を使用して、スポーンされているこのグラフを所有するエンティティへの応答内でいくつかのロジックをトリガする方法
Set Component Property および Get Component Property ノードを使用して、データ コンポーネント内のデータを設定および取得する方法(この場合は、ドアが開いているかどうかを示すブール値)
Entity > Get Entity World Position ノードを使用して、トランスフォーム コンポーネントがある場合に、そこからエンティティの位置を取得する方法
いずれかのノードのエンティティ変数に格納されている特殊な My Entity または (me) 値を使用して、このグラフを所有するエンティティのインスタンスを参照する方法
Entity > Get Entity Unit ノードを使用して、エンティティのユニット コンポーネントがある場合に、そこに割り当てられたユニットのインスタンスを取得する方法
Event > External In Event の実行に応答して、エンティティのフローからいくつかのロジックをトリガする方法レベル フロー グラフから、またはstingray.FlowComponent.trigger_flow_event() Lua 関数を呼び出して、このイベントをトリガすることができます。プロジェクトの Lua コード内で FlowComponent マネージャにアクセスする方法、および使用する方法については、「ゲームプレイ中にエンティティを操作する」を参照してください。
エディタ内でエンティティのフロー コンポーネントを設定するには:
Asset Browser または Explorer パネルのいずれかでエンティティを選択します。
Property Editor で新しい Flow コンポーネントをエンティティに追加します。
フロー グラフを保存したリソースをポイントするように、新しいフロー コンポーネントの Flow プロパティを設定します。
エンティティの動作を設定するには、Lua を使用すると便利です。フロー内で公開されているよりも多くの API 関数にアクセスできるからです。
スクリプト動作設定に関連する作業の多くは、Lua モジュールを作成することです。
ユーザ独自のエンティティに対して動作モジュールの記述を開始する最適な方法は、core/components/templates/script_component.template フォルダにあるテンプレートを使用することです。これはユーザ独自の動作を構築するための良好な(多くは機能面の)基盤となります。一部の複雑な項目は事前に設定されています。
このファイルをプロジェクトにコピーし、.lua 拡張子の付いた名前に変更します。
テンプレートを編集し、MyBehavior をコントロール対象のエンティティを説明するような一意の名前に変更します。
テンプレートへの関数の実装を完了します。または必要に応じて関数を変更します。
唯一の絶対要件は、モジュールが component というフィールドが含まれるオブジェクトを返す必要があることです。次に、この component フィールドは、name フィールドに含まれるオブジェクトを参照する必要があります。
この component オブジェクトには、スクリプト コンポーネントがエンティティの寿命内のさまざまな時に検索する特定の関数が含まれている場合もあります。(これらはテンプレート スクリプトで部分的に実装された関数です)。モジュールでこれらの関数のいずれかを定義すると、スクリプト コンポーネントは指定された時間にこれらを自動的に呼び出します。
たとえば、コンポーネントに spawned() 関数を作成すると、このモジュールに関連付けられたスクリプト コンポーネントを持つエンティティがスポーンされるたびに、その関数が自動的に呼び出されます。これにより、エンティティに必要な初期化を実行できます。同様に、update() 関数を作成した場合、このモジュールに存在するエンティティが関連付けられている限り、この関数は各フレームを体系的に呼び出します。
スクリプト コンポーネント モジュール内に設定できるすべての関数、および各関数に渡されるパラメータの完全なリストについては、core/components/templates/script_component.template ファイルを参照してください。
このスクリプトを記述する上での留意点は、すべてのゲーム ワールドでモジュールが関連付けられている「すべての」エンティティを処理する必要があることです。このスクリプトで各エンティティに対して定義するコンポーネント オブジェクトの個別のコピーはなく、ゲーム内にはこの Lua オブジェクトのインスタンスは 1 つ だけあります。関連付けられているエンティティの 1 つが初めてスポーンされたときに、スクリプト モジュール自体は一度だけ実行されます。その後は、このモジュールの関数の 1 つ(update() 関数など)を呼び出す必要があるたびに、関数は「一回」だけ呼び出されます。これらの関数を実装するときには、コンポーネントは、そのコンポーネントに関連付けられているすべてのエンティティ インスタンスのイベントを処理する必要があることに注意してください。
たとえば、テンプレート ファイルを確認すると、spawned() と unspawned() に事前に作成された関数定義があり、world_data フィールドに現在コンポーネントを使用しているすべてのエンティティに関する状態の情報をキャッシュすることが分かります。このキャッシュ情報は update() 関数で使用され、更新が必要なすべてのエンティティをループします。
スクリプトを require する必要がなくなったことに留意してください。これは、スクリプト コンポーネントによってゲーム内の Lua 環境に自動的にロードされます。
また、その他のいくつかの実施例を core/entities/vector_fields 内で参照できます。これらのスクリプト コンポーネントは、レベル内でパーティクルを吹き飛ばす風のエフェクトを設定します。ベクトル フィールドとこれらのスクリプト コンポーネントの使用方法に関する背景情報については、「ベクトル フィールド(風)のエフェクトを設定する」を参照してください。
エディタ内でエンティティのスクリプト コンポーネントを設定するには:
Asset Browser または Explorer パネルのいずれかでエンティティを選択します。
Property Editor で新しい Script コンポーネントをエンティティに追加します。
新しいスクリプト コンポーネントが Lua モジュールを指すように、その Script プロパティを設定します。
プロジェクトの Lua コードでは、モジュールで定義したコンポーネント オブジェクトへの直接アクセスはありません。ただし、stingray.ScriptComponent マネージャ API を介してコンポーネントを操作できます。これは stingray.EntityManager.script_component() を呼び出して取得します。
たとえば、ScriptComponent.broadcast() を使用して、スクリプト コンポーネント マネージャで自動的に特定の関数を呼び出すことができます。これをその関数を定義するすべてのスクリプト コンポーネント内で行うことができます。
stingray.ScriptComponent マネージャは、ワールド内のすべてのスクリプト コンポーネントを管理します。このため、特定の動作に関連付けられているエンティティだけを操作する場合は、ScriptComponent.instance_ids_with_script() または ScriptComponent.entities_with_script() を呼び出して、そのリストをフィルタすることもできます。
スクリプト コンポーネント インスタンスのフィルタ済みリストを取得したら、ScriptComponent.dispatch() を呼び出すことで、その動作リスト上の特定の関数のみをマネージャで呼び出すことができます。