コンポーネントベースのゲームオブジェクトを使用するゲームを作成していますが、各コンポーネントがゲームオブジェクトと通信する方法を実装するのに苦労しています。すべてを一度に説明するのではなく、関連するサンプルコードの各部分について説明します。
class GameObjectManager {
public:
//Updates all the game objects
void update(Time dt);
//Sends a message to all game objects
void sendMessage(Message m);
private:
//Vector of all the game objects
std::vector<GameObject> gameObjects;
//vectors of the different types of components
std::vector<InputComponent> input;
std::vector<PhysicsComponent> ai;
...
std::vector<RenderComponent> render;
}
GameObjectManager
すべてのゲームオブジェクトとそのコンポーネントを保持しています。また、ゲームオブジェクトの更新も行います。これは、コンポーネントベクトルを特定の順序で更新することによって行われます。配列の代わりにベクトルを使用するので、一度に存在できるゲームオブジェクトの数に実質的に制限はありません。
class GameObject {
public:
//Sends a message to the components in this game object
void sendMessage(Message m);
private:
//id to keep track of components in the manager
const int id;
//Pointers to components in the game object manager
std::vector<Component*> components;
}
GameObject
クラスは、その構成要素が何であるかを知っているし、彼らにメッセージを送ることができます。
class Component {
public:
//Receives messages and acts accordingly
virtual void handleMessage(Message m) = 0;
virtual void update(Time dt) = 0;
protected:
//Calls GameObject's sendMessage
void sendMessageToObject(Message m);
//Calls GameObjectManager's sendMessage
void sendMessageToWorld(Message m);
}
このComponent
クラスは純粋に仮想なので、さまざまなタイプのコンポーネントのクラスがメッセージの処理方法と更新方法を実装できます。メッセージを送信することもできます。
さて問題は、コンポーネントを呼び出すことができますどのように起こるsendMessage
の関数をGameObject
とGameObjectManager
。私は2つの可能な解決策を思いつきました:
Component
そのへのポインタを与えるGameObject
。
ただし、ゲームオブジェクトはベクター内にあるため、ポインターがすぐに無効になる可能性があります(のベクターについても同じことが言えますが、GameObject
うまくいけば、この問題を解決することでベクターも解決できます)。ゲームオブジェクトを配列に配置することもできましたが、その場合はサイズに任意の数を渡す必要があり、サイズが不必要に高くなり、メモリを浪費する可能性があります。
Component
へのポインタを与えますGameObjectManager
。
ただし、コンポーネントがマネージャーの更新関数を呼び出せるようにしたくありません。私はこのプロジェクトに取り組んでいる唯一の人ですが、潜在的に危険なコードを書く習慣をつけたくありません。
コードを安全でキャッシュに優しい状態に保ちながら、この問題を解決するにはどうすればよいですか?