web-dev-qa-db-ja.com

エンティティコンポーネントシステムで設計されたゲームエンジンでカスタムルールを許可するにはどうすればよいですか?

したがって、私はゲームエンジンについて多くの研究を行ってきましたが、エンティティコンポーネントシステム(ECS)は、使用するのに最も柔軟で拡張可能な設計のようです。

要約すると、ECSの基本的な考え方は、コンポーネントの単なるコンテナーであるエンティティーがあり、異なるコンポーネントは異なる機能に対応しますが、データを格納するだけであるということです。たとえば、タワーの防衛ゲームでは、移動可能なコンポーネントを持つタワーエンティティを使用できますが、実際に格納されるすべてのコンポーネントは、タワーの現在の方向と速度になります。

タワーを移動する実際のロジックは、システムで制御されます。システムが行うことは、特定のコンポーネントを持つすべてのエンティティを反復処理し、それに応じてそれらを変更することです。したがって、Moveable Entities(移動可能なコンポーネントがあります)のみを見て、それに応じてデータを更新する移動システムがあります。

したがって、ゲームに関するすべての情報を格納するゲームオブジェクトを設計する方法に関しては、これらすべてが理にかなっています。私の質問は、カスタムのユーザー定義ルールをこのモデルにどのように組み込むのですか?私が持っているのはゲームエンジンなので、ゲームごとに、またはゲーム内のレベルごとに異なる特定のユーザー定義のルールを処理できる必要があります。

たとえば、敵の特定の範囲内にいる場合を除いて、すべてのタワーを移動させるというルールが必要だとします。このロジックはどこにありますか?それがムーブメントシステムに存在する場合、ゲームエンジンが正しく機能するはずの方法ではなく、ゲームごとに新しいムーブメントシステムを作成する必要がありますか?全体のアイデアは、あなたがそれにどんなゲームを与えても、システムがそれを処理できるということです。別の「ルール」システムが必要ですか?

5

まず、警告:他のプログラミングドメインよりもさらにeveryゲーム開発における設計上の決定はトレードオフです。 「正しい」答えは、「あなたが作っているゲームで何がうまくいくか」です。

はい。私たちが取ることができるいくつかのアプローチがあります:

  1. 小さな既知の一般的な動作のセットがある場合は、インラインで記述して、ユーザーがパラメーターを微調整できるようにします。 (つまり、このタワーはどの敵を回避するか、どれくらい離れている必要があるか、など)。これは最も簡単で保守可能なアプローチですが、動作が異なるほどスケーリングが不十分になります。

  2. 関数はデータにすることができます! Cでは、これは関数ポインターです。他の言語にも同等のものが存在します。エンティティを作成するコードは、エンティティにどのように動作するかを伝える機能を与える責任があります。

Cでは、次のようになります。

// Define a function pointer type.
typedef void BehaviorFunc(Entity * this);

struct FooComponent {
    BehaviorFunc * my_behavior;
    // Other data as needed...
}

// User code:
void MyBehaviorFunc(Entity * this) {
    DoTheThing();
}
// ...
{
    FooComponent * f = AddFooComponent();
    f->my_behavior = MyBehaviorFunc;
}

// Update:
void UpdateFooComponent(FooComponent * f) {
    // stuff
    f->my_behavior(GetEntityFromComponent(f));
    // more stuff
}

ここにも他のオプションがあります。非プログラマが動作を定義できるようにする必要がある場合は、関数ポインタを動作ツリー、コンパイルされたスクリプトコードなどに置き換えることができます。ただし、これらはすべてmuchより複雑です。したがって、実際に追加の柔軟性が必要でない限り、気にする必要はありません。エンジンとクライアントコードの両方に対して、システムをより一般的にするほど、実装(および最適化)が難しくなることに注意してください。

3
ACEfanatic02

この質問は数年前に尋ねられましたが、私は実際にEntity Component System[〜 #〜] ecs [〜#〜])アーキテクチャは私自身であり、あなたやコミュニティが役立つと思うかもしれないという洞察を持っているかもしれません。

注:frameworkECSフレームワークおよびgame engine。 ECSフレームワークは、特定のタイプのゲームエンジンにすぎません。さらに、卵をクラックする方法は複数あり、ECSフレームワークの設計についても同様です。 ECSフレームワークが構築される定義は1つではありません。ただし、それらの設計を導く一般的に受け入れられている特性がいくつかあります。なるべく特性だけにこだわるようにしています。ここで説明するいくつかのことは、別のECSアーキテクチャについて話すときに、より柔軟になる可能性があります。そのような古い質問なので、OPは明確に理解できない可能性があるため、OPが質問の表現に基づいて求めているECSアーキテクチャの種類を少し試してみます。


質問/コメント1

「たとえば、敵の特定の範囲内にいる場合を除いて、すべてのタワーを移動させるというルールが必要だとします。このロジックはどこに存在しますか?」

移動に関連するルールは、タワー移動ロジックの特別なケースとして実装される可能性が最も高いでしょう。これを行う1つの方法の例として、以下を参照してください。

_class TowerMovementSystem
{
    public void update()
    {

        .
        .
        .

        var enemies = worldManager.findLocalEnemies(positionComponent);

        if(enemies.empty())
        {
            // Move towers...
        }
    }
}
_

上記の例には多くの詳細がありませんが、重要なポイントは、システムに移動するためのロジックです。 update()関数は、ゲームループやシステム管理ユーティリティなど、より高いレベルのフレームワークコードによって実行されます。つまり、システム開発者がゲーム開発者によって記述されているにもかかわらず、update()関数がゲーム開発者によって記述されたコードによって呼び出されることはほとんどありません。


質問/コメント2

「ムーブメントシステムに存在する場合、ゲームごとに新しいムーブメントシステムを作成する必要があります...」

正しい。ゲームごとに動きが異なります。 マリオ小惑星 の宇宙船とは非常に異なる動きをします。ゲームデザイナーは、その動きを定義する責任があります。


質問/コメント3

「……ゲームエンジンが正しく機能するはずの方法ではありませんか?全体のアイデアは、どんなゲームでもフィードし、システムがそれを処理できるということです。」

この質問であなたがどこから来たのか理解しました。私が最初に趣味のゲーム開発に入ったとき、この質問のバリエーションは私の心を悩ませました。最終的には、長年にわたっていくつかのゲームエンジンを使用した経験の一部だけでなく、「ゲームに餌をやる」と言ったときにあなたが着いているという考えを評価することからも答えが出ました。

技術的な意味でのゲームとは何ですか?私はここで哲学や何かを得ようとしているわけではありませんが、フレームワークにフィードしていることを確実に言えるように、実用的な定義が必要です。私にとって、ゲームはエンティティのコレクションであり、プレーヤーや他のエンティティとの相互作用を通じて状態が変化します。相互作用は、一連のルールによって制約されます。

例をいくつか示します。

Pong-The Pong Ball

Pongボール(entity)は、その速度に基づいて位置(state change)を変更します。壁から跳ね返らない限り(rule constraint)、直線で移動します(rule constraint)(state change)またはパドル(rule constraint)(state change)。

マリオ-2Dゴンバ

Goomba(entity)は、その速度に基づいて位置を変更します(state change)。直線で左または右(rule constraint)に移動します(rule constraint) 。障害物(ルール制約)にぶつかると、方向が変わり(state change)、動き続けます。マリオが(rule constraint)に踏まれると死ぬ(state change)。

上記のすべてがECSアーキテクチャに非常にうまく対応しています(ECSアーキテクチャがゲーム開発で非常に一般的になっている理由の1つ)。

_Definition Concept -> ECS Architecture Concept -> Examples
Entities -> Entities -> Pong ball, Mario Goomba
States -> Components -> PositionComponent, VelocityComponent, LifeComponent
Rule Constraint Sets -> Systems -> PongBallMovementSystem, GoombaMovementSystem, MarioMovementSystem
_

したがって、フレームワークにfeedするのは、エンティティ、コンポーネント、およびシステムです。システムはフレームワークの一部ではなく、フィードまたはフレームワークに登録されています。システムは各ゲーム(またはレベル)に固有のルールセットを実装し、フレームワークはそれらを操作して、エンティティの状態変更を引き起こす相互作用を推進します。それらはフレームワークの外部に実装されます。これはゲーム開発者(ほとんどの場合)が作成するか、フレームワーク開発者が実装し、ゲーム開発者が使用するための便利なアドオンパッケージとして出荷されます。

フレームワーク開発者がいくつかの既製のシステムを提供する場合、問題は彼らが自分のソフトウェアで作られるゲームの種類を推測することしかできないことになります。これにより、「8倍ジャンプ」や「敵の範囲内で停止」などのカスタムルールを持たない一般的なシステムのみを提供するように制限されます(ただし、変更および再構築またはビルドできるソースコードを提供する場合を除き、おそらくその価値よりも多くのトラブル)。


質問/コメント4

「私が持っているのはゲームエンジンであるため、ゲームごとに、またはゲーム内のレベルごとに異なる可能性がある特定のユーザー定義ルールを処理できる必要があります。」

そのステートメントは正しくありません。フレームワークは、ゲームを定義するためのメカニズムを提供しますが、ゲームのルールやレベルの制約など、ゲームの詳細を知りません。これらは、先ほどお話ししたシステムの問題です。フレームワークは、ゲームを構築するための基盤のようなものです。フレームワークは次のような懸念に対処します

  • 登録/登録解除/作成/破棄
    • エンティティ
    • 部品
    • システム
  • システムの実行。
  • フレームワーク間通信(システム-システム通信、ロギングなど)
  • ゲームループの進行状況
    • イベントドリブン
    • 時間駆動
      • 固定タイムステップ
      • 可変時間ステップ
  • エンティティ定義
    • データを持つオブジェクト
    • 整数IDのみ
  • コンポーネントの保存方法
    • エンティティIDをキーとして各システムにコピーを保存します
    • エンティティオブジェクトに格納する
    • エンティティIDを使用してコンポーネントマネージャーに保存する
  • システムの通信方法
    • イベントメッセージ
    • コールバック
    • オブザーバーパターン
    • 通信は許可されていません
  • もっともっと...

ご覧のとおり、このフレームワークは特定のゲームやゲームルールの問題に対処していません。 ECSアーキテクチャを使用してゲームを構築するために必要なメタ懸念に対処します。


0
MrJman006