2017-02-08 10 views
2

私は最初のゲームエンジンを開発しており、壁に当たっています。現在、私はいくつかのシステムマネージャクラス(graphisManager、PhysicsManagerなど)内のコンポーネントオブジェクトへのポインタを保持するコンポーネントポインタのベクトルを持つEntity基本クラスを持っています。ここでは(主な問題に焦点を当てるストリップダウン)私の現在のエンティティヘッダは次のとおりです。ゲームエンジンでコンポーネントを最適に管理するにはどうすればよいですか?

Entity.h

class Component; 

namespace BlazeGameWorld 
{ 
    class Entity 
    { 
    public: 
     BlazeFramework::Math::Vector2D position; 

    protected: 
     Vector<Component*> components; 

     static BlazeGraphics::GraphicsManager graphicsManager; 
     static BlazePhysics::PhysicsManager physicsManager; 
     static BlazeInput::InputManager inputManager; 
     //....other managers 

    private: 

     /////////////////////////////////////////////////////////////////////// 

    public: 
     Entity(); 
     ~Entity(); 

     virtual bool Initialize(); 
     virtual bool Shutdown(); 

     virtual void Update() = 0; 

     void AddComponent(Component* p_component); 

     //Part of the broadcast messaging system for components to be able 
     //to talk to one another in a decoupled way. 
     void SendMessage(uint messageID); 

    protected: 

    private: 
    }; 
} 

あなたが見ることができるように、アイデアが実際にポインタを管理します静的するSystemManagerクラスを持つことですヒープ上のコンポーネントここでは潜在的なPhysicsManagerクラスのラフヘッダーはある(そしてそれは他のマネージャークラスについても同様です):

PhysicsManager.h

class PhysicsComponent; 

namespace BlazePhysics 
{ 
    class PhysicsManager 
    { 
    public: 

    protected: 
     int numPhysicsComponents; 
    private: 
     Vector<PhysicsComponent*> physicsComponents; 

     ///////////////////////////////////////////////////////////// 

    public: 
     PhysicsManager(); 
     ~PhysicsManager(); 

     bool Initialize(); 
     bool Shutdown(); 

     void Update(); 

     template <typename PhysicsComponentType> 
     PhysicsComponentType* CreatePhysicsComponent(); 

    private: 
    }; 

    //template definitions 
    template <typename PhysicsComponentType> 
    PhysicsComponentType* PhysicsManager::CreatePhysicsComponent() 
    { 
     PhysicsComponentType* physicsComponent = new PhysicsComponentType 
     physicsComponents.push_back(physicsComponent); 

     return physicsComponents.at(numPhysicsComponents++); 
    } 
} 

だから私はPhysicsMangerベクトル内のすべての異なるphysicsComponentのポインタを格納することができます(ポインタへCollisionComponents、PositionComponentsなど)。問題は、特定の物理コンポーネント固有のメソッドを呼びたい場合、コンパイルできないということです。例えば、(PhysicsManagerの更新ループで)collisionComponentのCheckCollision()メソッドを更新するには、forループの中で言うことができません。physicsComponents.at(i).CheckCollisionコンパイラはCollisionComponentをコンパイル時に認識しないためです。多分配列の中のコンポーネントの型を推定し、それがCollisionComponentと一致すればCheckCollisionメソッドを呼び出す方法がありますか?または、これは一種のように思われるので、これを実装する方が良いですか?

+0

ここでコンポーネントベースのエンジンを見てうれしいですが、私はあなたと同様の構造の私の最初のゲームエンジンに取り組んでいます。しかし、私はゲームエンジンのリファレンスを各システムに渡し、リファレンスを使用して他のシステムにアクセスできるようにしました。私はそれが良いかどうかわからないが、少なくともそれは働いている。もっと良い解決策を見たいと思っています。XD –

+0

あなたのことを聞いてうれしいです。私は、さまざまなコンポーネントタイプの配列の配列を実装するいくつかのソリューションを検討しています。私がこのような何かを実装する方法を見つけ出すことができれば、私はここで解決策を投稿するかもしれません。 – Jason

答えて

2

エンティティはシステムについて知ってはいけません。エンティティは単なるコンポーネントの集合でなければなりません。さもなければ、別のエンジンシステムを導入するプロセスはエンティティクラスを変更する必要があり、これはECSの全目的に反します。

システムもコンポーネントを管理するべきではありません。 1つのシステムは、いくつかのコンポーネントを使用してもよく、多くのシステムは、例えば、位置/衝突ジオメトリコンポーネント。

だから、私の意見では:すべての処理がシステム内で行われている間

  • コンポーネント、理想的には、単純なデータのみのクラスでなければなりません。
  • エンティティは、コンポーネントの追加と削除の方法を提供するだけで、特定のコンポーネントがあるかどうかを示す を提供する必要があります。
  • エンティティマネージャの種類の中には、システムがキャッシュにアクセスするためにキャッシュに適した方法でコンポーネントを保存しなければならず、システムに特定のコンポーネント/タグを持つエンティティのリストを提供できる必要があります。

このように、たとえば、一部のエンティティに対してスクリプト動作を追加する場合は、ScriptComponentScriptingSystemを追加するだけです。既存のコードはすべて変更する必要はありません。

This questionには、このトピックで非常に有用なリソースがたくさんあります。

+0

さて、Entity Mangerクラスは、ゲーム内のEntityのすべてのコンポーネントを扱う責任があるはずですか?そして、すべてのシステム(graphicsSystem、PhysicsSystem、ScriptingSystem)は、コンポーネントの使用や交換が可能ですか? – Jason

+0

@Jasonそれはもっと記述的なものと呼ぶことができますが、おそらくそれはシステム自体ではありません。システムは、一般的に、コンポーネントを追加/削除しません。あなたの世界/シーンはそうです。 ECSといくつかのオープンソースの実装に関する論文がたくさんありますが、それらを必ずチェックしてください。 – w1ck3dg0ph3r

+0

@Jasonまた、Vittorio RomeoのCppCon15には、[ECSの実装についての素敵な話](https://www.youtube.com/watch?v=NTWSeQtHZ9M)がありました。 – w1ck3dg0ph3r

関連する問題