オブジェクト プールが必要かどうかはよくわかりませんが、これが最も実行可能なソリューションのように思えますが、これには望ましくない短所がいくつかあります。エンティティがオブジェクト プール内に格納されるゲームを作成しています。これらのエンティティは new で直接割り当てられず、代わりに astd::deque
がそれらのメモリを処理します。
これは私のオブジェクトプールが多かれ少なかれどのように見えるかです:
struct Pool
{
Pool()
: _pool(DEFAULT_SIZE)
{}
Entity* create()
{
if(!_destroyedEntitiesIndicies.empty())
{
_nextIndex = _destroyedEntitiesIndicies.front();
_destroyedEntitiesIndicies.pop();
}
Entity* entity = &_pool[_nextIndex];
entity->id = _nextIndex;
return entity;
}
void destroy(Entity* x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
}
private:
std::deque<Entity> _pool;
std::queue<int> _destroyedEntitiesIndicies;
int _nextIndex = 0;
};
エンティティを破棄すると、ID がキューに追加され_destroyedEntitiesIndicies
、ID が再利用され、最後に ID が 0 に設定されます。これに対する唯一の落とし穴は、破棄する場合です。エンティティを作成してすぐに新しいエンティティを作成すると、以前に破棄されたエンティティが更新され、作成されたばかりのエンティティと同じになります。
すなわち
Entity* object1 = pool.create(); // create an object
pool.destroy(object1); // destroy it
Entity* object2 = pool.create(); // create another object
// now object1 will be the same as object2
std::cout << (object1 == object2) << '\n'; // this will print out 1
これは私には正しくないようです。どうすればこれを回避できますか? 明らかに、上記はおそらく起こらないでしょう (次のフレームまでオブジェクトの破壊を遅らせるため)。しかし、これは、エンティティの状態をファイルに保存する際、またはそれらの行に沿って何らかの障害を引き起こす可能性があります。
編集:
それらを破壊するために NULL エンティティを実行したとしましょう。プールからエンティティを取得したり、実際のエンティティへのポインタのコピーを保存したりできたらどうしますか? 破棄されたときに他のすべての重複エンティティを NULL にするにはどうすればよいですか?
すなわち
Pool pool;
Entity* entity = pool.create();
Entity* theSameEntity = pool.get(entity->getId());
pool.destroy(entity);
// now entity == nullptr, but theSameEntity still points to the original entity