2017-12-29 11 views
0

私はこのエラーをしばらく解決しようとしていますが、これを修正する方法がわかりません。C++ Map/Set iteratorインクリメンタルエラーなし

私は開発中のゲーム内のすべてのエンティティを処理するEntityManagerを持っています。各エンティティは、各エンティティが与えられたランダムIDでソートされたマップに追加されます。通常は「この」のようなのでを通じて、

void EntityManager::RemoveEntity(Entity* entity) 
{ 
    entities.erase(entity->GetID()); 
    delete entity; 
} 

と削除されたエンティティに渡す:私はゲーム内のエンティティを削除したい場合は

void EntityManager::AddEntity(Entity* entity) 
{ 
    int ID = rand(); 
    for(int i = 0; i < IDS.size(); i++) 
    { 
     if(IDS[i] == ID) 
     { 
      ID = rand(); 
      i = 0; 
     } 
     else 
     { 
      break; 
     } 
} 

entity->SetID(ID); 
entities.insert(pair<int, Entity*>(ID, entity)); 

、私は単にこのRemoveEntity関数を呼び出します。

virtual void Effect::RemoveEffect() 
{ 
    DeleteEntity(this); 
} 

void DeleteEntity(Entity* entity) 
{ 
    entityManager->RemoveEntity(entity); 
} 

ゲームのすべてが、このエンティティクラスから途中で継承されます。

私がいる問題は、私は「RemoveEntity」関数を呼び出すと、それはこのコード行を実行したときに発生し、このエラーです:

entities.erase(entity->GetID()); 

ゲームは単に地図/セット・イテレータでクラッシュするわけではありませんインクリメンタルエラーと私は理由を理解できません。私はこのエラーが発生した人についての他のトピックを見てきましたが、解決方法はforループのようなものに変更を加えることです...私は持っていません。

私は注意する必要がありますけれども、このエラーが唯一のこれまでのところ、私はエンティティをこのように削除していたときに発生すること:私は、エンティティが削除されたときに遅延させるためのタイマーを持って

destroyTimer += deltaTime; 
if(destroyTimer >= destroyDelay) 
{ 
    entityManager->RemoveEntity(this); 
} 

。このコードセクションは、GameLoopの間にフレームごとに呼び出されるUpdate Functionにあります。上記のようなタイマーなしで即座に "RemoveEntity"関数を呼び出しているにも関わらず、Entityを削除するとエラーは発生しませんが、エラーが発生する理由はわかりません。

何が起こっているのか知っていますか? (

void PointEffect::Update(float deltaTime) 
{ 
    Entity::Update(deltaTime); 

    destroyTimer += deltaTime; 
    if(destroyTimer >= destroyDelay) 
    { 
     RemoveEffect(); 
    } 
} 

エンティティ::更新:

EDIT は上記の例に示すRemoveEntity関数は、完全な更新ループは次のようになり、各エンティティが持つエンティティの更新機能の範囲内でありますdeltaTime)だけこれを呼び出す:

virtual void Update(float deltaTime) 
{ 
    if(animationHandler != nullptr) 
    { 
     animationHandler->Update(deltaTime);    
    } 

    if(moveSpeed != 0) 
    { 
     position += velocity * moveSpeed; 
    } 

    if(collision != nullptr) 
    { 
     collision->Update(GetSpriteRect(), position); 
    } 
} 

各エンティティにある更新ループがある場合、GameStates更新機能によって呼び出されたループを更新し、実際のEntityManagersによって呼び出されGameLoop自体が呼び出すだけです。 EntityManagerの更新機能:

void EntityManager::Update(float deltaTime) 
{ 
if(!entities.empty()) 
{ 
     for(const auto entity : entities) 
     {   
      entity.second->Update(deltaTime); 
     } 
    } 
} 

GameState更新機能:

void MainGame::Update(float deltaTime) 
{ 
    entityManager->Update(deltaTime); 
} 
+2

[MCVE]を投稿してください。また、「自分自身を削除する」というエンティティを持つことは、コードの臭いと悪いデザインの兆候です。あなたはおそらくそれを世話する何らかのマネージャーを望んでいるでしょう –

+1

これはあなたの[前の質問]とどのように違いますか(https://stackoverflow.com/questions/47851790/c-game-map-set-iterator-no-incrementable-エラー) – 1201ProgramAlarm

+0

@ 1201ProgramAlarmそれはちょっと混乱していましたが、私は今問題を見つけましたが、私が何を話しているのか本当に知りませんでした。 – codelyoko373

答えて

1

EntityManager::Updateでそのforループが実行されている間、あなたはentitiesからentityを削除することはできません。これは、ループがまだイテレータを使用しているためです。ループが実行されている間に削除するエンティティをメモするか、従来のforループを使用して、ループのイテレータを次の要素に進めてUpdateを呼び出す必要があります(これは、他のエンティティを削除しないだけです)。

+0

これは機能します!、ありがとうございます:) – codelyoko373