[Solved] unordered_map for storing/removing game objects

Get answers to all your basic programming questions. No Ogre questions, please!
User avatar
Oceax
Gnoblar
Posts: 19
Joined: Wed Sep 10, 2008 4:14 pm

[Solved] unordered_map for storing/removing game objects

Post by Oceax »

To get better running time, i designed my game engine with unordered_map for game objects where each objects unique id is a key. But iterating over unordered_map seems to iterate also over stuff that has been erased and are invalid ( key remains but not its mapped object)

I declare
boost::unordered_map<int, GameObject*> gameObjects

So i can do:
gameObjects[obj.id] = obj
obj = gameObjects[id for some obj i want]

And everything worked great when i was just adding stuff and game objects was not killed.

But now for every frame, i iterate an unordered_map X containing pointers to all objects that are relevant for updating:
Loop()
- Update X
- - iterate objects and update states
- Remove objects that are dead in X
- - put pointers to objects marked for removal in zombie list (the objects will be deleted later in looping zombie list)
- - erase object (pointer) in X so that it will not be considered for update next time.

The problem is that if in Removal part i do X.erase(obj with id 6) then the next time it does Update X it still iterates over it
iterator->first = 6
iterator->second = INVALID (the game object) :cry:

Why does it keep the key and considers it for iteration when the element was erased? :?
Last edited by Oceax on Fri Oct 26, 2012 9:59 pm, edited 1 time in total.
User avatar
Herb
Orc
Posts: 412
Joined: Thu Jun 04, 2009 3:21 am
Location: Kalamazoo,MI
x 38

Re: unordered_map for storing/removing game objects

Post by Herb »

hmmm....what you're saying shouldn't be a problem. You can typically call erase on both the key or iterator value. If you did something like map.erase(5), then went into a for loop, it should not iterate over that key 5. NOTE: If you call erase() within a loop performing an iteration on the collection, the iterator will become invalid. Here is an explation and code sample of the erase function if that helps. Maybe you're doing something in the code that I don't know about that's causing it...
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: unordered_map for storing/removing game objects

Post by bstone »

Yeah, it's more likely that you're doing something wrong when erasing stuff from your map. Post the snippet of your code where you invoke erase().
User avatar
Oceax
Gnoblar
Posts: 19
Joined: Wed Sep 10, 2008 4:14 pm

Re: unordered_map for storing/removing game objects

Post by Oceax »

I don't post the whole Update because it's a lot of code with state machines. Anyway, doing assignments like this gameObjects[obj.id] = obj is very ugly and bad. I should call a function that then puts in unordered_map, same with Get .

loop
- Update states
- Remove

Update object state - Program crashes on last line because *iter->second is invalid, but prints iter->first that contains the key for element that was removed in the loop before

Code: Select all

	UnitsType::iterator iter = gameListener.objectMgr->units.begin();
	while (  iter != gameListener.objectMgr->units.end(); iter++ )
	{
		Ogre::LogManager::getSingleton().logMessage("UpdateUnits with size: " +  Ogre::StringConverter::toString(gameListener.objectMgr->units.size()));

		Unit& unit = *iter->second;

		Ogre::LogManager::getSingleton().logMessage("UpdateUnits: Iterator value: " + Ogre::StringConverter::toString(iter->first));
		Ogre::LogManager::getSingleton().logMessage("UpdateUnits: Unit: " + Ogre::StringConverter::toString(unit.id));
	}

Object removal

Code: Select all

	Ogre::LogManager::getSingleton().logMessage("Cleaning up units to be removed");
	UnitsType::iterator iter2 = gameListener.objectMgr->units.begin();
	while (  iter2 != gameListener.objectMgr->units.end() )
	{
		Unit& unit = *iter2->second;
		Ogre::LogManager::getSingleton().logMessage(" - Cleaning with iterator id: " + Ogre::StringConverter::toString(iter2->first));
		if(unit.destroyed)
		{
			Ogre::LogManager::getSingleton().logMessage(" - unit is destroyed: " + Ogre::StringConverter::toString(unit.id));
			Ogre::LogManager::getSingleton().logMessage("ERASING UNIT: " + Ogre::StringConverter::toString(unit.id) );
			
			// Remove from selected units IF IT IS SELECTED
			gameListener.objectMgr->selectedUnits.erase(unit.id);
			
			// Remove from CellSpacePartition (find neighbours optimization)
			Ogre::LogManager::getSingleton().logMessage(" - pCellSpacePartition->RemoveEntity(&unit)");
			gameListener.pCellSpacePartition->RemoveEntity(&unit);
			Ogre::LogManager::getSingleton().logMessage(" - pCellSpacePartition->RemoveEntity(&unit) done");

			// Remove from units
			Ogre::LogManager::getSingleton().logMessage(" - units size before: " + Ogre::StringConverter::toString(gameListener.objectMgr->units.size()));
			gameListener.objectMgr->units.erase(iter2++);
			Ogre::LogManager::getSingleton().logMessage(" - units size after: " + Ogre::StringConverter::toString(gameListener.objectMgr->units.size()));
		}
		else
		{
			++iter2;
		}
	}
User avatar
Oceax
Gnoblar
Posts: 19
Joined: Wed Sep 10, 2008 4:14 pm

Re: unordered_map for storing/removing game objects

Post by Oceax »

Logg file. The interesting part is
16:46:21: ERASING UNIT: 6
...
16:46:21: - units size before: 12
16:46:21: - units size after: 11
and later
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 6

Suddenly UpdateUnits size is 12... I have not added any new units.
Again, doing gameObjects[obj.id] = obj directly everywhere is very bad. I'm probably trying to compare values but accidently
creates a new entry in the map somewhere. :shock:

Code: Select all

16:46:21: Cleaning up units to be removed
16:46:21:  - Cleaning with iterator id: 0
16:46:21:  - Cleaning with iterator id: 1
16:46:21:  - Cleaning with iterator id: 2
16:46:21:  - Cleaning with iterator id: 3
16:46:21:  - Cleaning with iterator id: 4
16:46:21:  - Cleaning with iterator id: 5
16:46:21:  - Cleaning with iterator id: 6
16:46:21:  - unit is destroyed: 6
16:46:21: ERASING UNIT: 6
16:46:21:  - pCellSpacePartition->RemoveEntity(&unit)
16:46:21: CellSpacePartition RemoveEntity
16:46:21:  - CellSpacePartition size before: 2
16:46:21:  - CellSpacePartition size after: 1
16:46:21:  - pCellSpacePartition->RemoveEntity(&unit) done
16:46:21:  - units size before: 12
16:46:21:  - units size after: 11
16:46:21:  - Cleaning with iterator id: 7
16:46:21:  - Cleaning with iterator id: 8
16:46:21:  - Cleaning with iterator id: 9
16:46:21:  - Cleaning with iterator id: 10
16:46:21:  - Cleaning with iterator id: 11
16:46:21: UpdateUnits with size: 11
16:46:21: UpdateUnits: Iterator value: 0
16:46:21: UpdateUnits: Unit: 0
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 1
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours done, size(): 7
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: pTarget == 0
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - FindPreferredEnemy!2
16:46:21: - FindPreferredEnemy!3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 1
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours done, size(): 7
16:46:21: - FindPreferredEnemy!4
16:46:21: - neighbourObjects element0
16:46:21: - - neighbourObjects go->id3
16:46:21: - neighbourObjects element1
16:46:21: - - neighbourObjects go->id2
16:46:21: - neighbourObjects element2
16:46:21: - - neighbourObjects go->id1
16:46:21: - neighbourObjects element3
16:46:21: - - neighbourObjects go->id4
16:46:21: - neighbourObjects element4
16:46:21: - - neighbourObjects go->id5
16:46:21: - neighbourObjects element5
16:46:21: - - neighbourObjects go->id7
16:46:21: - neighbourObjects element6
16:46:21: - - neighbourObjects go->id8
16:46:21: - neighbourObjects done!
16:46:21: - preferredEnemy != 0
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.7
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: Strike!
16:46:21: - in_unit.definition.strikeRadius is: 3
16:46:21: - targetUnit->definition.baseRadius is: 0.5
16:46:21: - unitCircle.Collides(targetCircle) is: false
16:46:21: - StrikerID is: 0
16:46:21: - TargetId is: 7
16:46:21: - rotationProgress is: 1.#INF
16:46:21: - Collides?
16:46:21: -UpdatePositionAndRotation
16:46:21: -pCellSpacePartition
16:46:21: - - prevPosXZ: 124.568 120.73
16:46:21: UpdateEntity
16:46:21:  - OldIdx: 3871
16:46:21:  - NewIdx: 3871
16:46:21: -pCellSpacePartition done
16:46:21: -TerrainAdaption
16:46:21: -EnforceNonPenetrationConstraint
16:46:21: Unit done
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 1
16:46:21: UpdateUnits: Unit: 1
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 0
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours done, size(): 7
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: pTarget == 0
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - FindPreferredEnemy!2
16:46:21: - FindPreferredEnemy!3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 0
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours done, size(): 7
16:46:21: - FindPreferredEnemy!4
16:46:21: - neighbourObjects element0
16:46:21: - - neighbourObjects go->id3
16:46:21: - neighbourObjects element1
16:46:21: - - neighbourObjects go->id2
16:46:21: - neighbourObjects element2
16:46:21: - - neighbourObjects go->id0
16:46:21: - neighbourObjects element3
16:46:21: - - neighbourObjects go->id4
16:46:21: - neighbourObjects element4
16:46:21: - - neighbourObjects go->id5
16:46:21: - neighbourObjects element5
16:46:21: - - neighbourObjects go->id7
16:46:21: - neighbourObjects element6
16:46:21: - - neighbourObjects go->id8
16:46:21: - neighbourObjects done!
16:46:21: - preferredEnemy != 0
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.7
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: Strike!
16:46:21: - in_unit.definition.strikeRadius is: 3
16:46:21: - targetUnit->definition.baseRadius is: 0.5
16:46:21: - unitCircle.Collides(targetCircle) is: false
16:46:21: - StrikerID is: 1
16:46:21: - TargetId is: 7
16:46:21: - rotationProgress is: 1
16:46:21: - Collides?
16:46:21: -UpdatePositionAndRotation
16:46:21: -pCellSpacePartition
16:46:21: - - prevPosXZ: 126.16 121.964
16:46:21: UpdateEntity
16:46:21:  - OldIdx: 3871
16:46:21:  - NewIdx: 3871
16:46:21: -pCellSpacePartition done
16:46:21: -TerrainAdaption
16:46:21: -EnforceNonPenetrationConstraint
16:46:21: Unit done
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 2
16:46:21: UpdateUnits: Unit: 2
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 1
16:46:21: - Neighbours in cell 2 push_back with id: 0
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: pTarget == 0
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - FindPreferredEnemy!2
16:46:21: - FindPreferredEnemy!3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 1
16:46:21: - Neighbours in cell 2 push_back with id: 0
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - FindPreferredEnemy!4
16:46:21: - neighbourObjects element0
16:46:21: - - neighbourObjects go->id3
16:46:21: - neighbourObjects element1
16:46:21: - - neighbourObjects go->id1
16:46:21: - neighbourObjects element2
16:46:21: - - neighbourObjects go->id0
16:46:21: - neighbourObjects element3
16:46:21: - - neighbourObjects go->id4
16:46:21: - neighbourObjects element4
16:46:21: - - neighbourObjects go->id5
16:46:21: - neighbourObjects element5
16:46:21: - - neighbourObjects go->id7
16:46:21: - neighbourObjects element6
16:46:21: - - neighbourObjects go->id8
16:46:21: - neighbourObjects element7
16:46:21: - - neighbourObjects go->id10
16:46:21: - neighbourObjects element8
16:46:21: - - neighbourObjects go->id11
16:46:21: - neighbourObjects done!
16:46:21: - preferredEnemy != 0
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.7
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: Strike!
16:46:21: - in_unit.definition.strikeRadius is: 3
16:46:21: - targetUnit->definition.baseRadius is: 0.5
16:46:21: - unitCircle.Collides(targetCircle) is: false
16:46:21: - StrikerID is: 2
16:46:21: - TargetId is: 7
16:46:21: - rotationProgress is: 1.#INF
16:46:21: - Collides?
16:46:21: -UpdatePositionAndRotation
16:46:21: -pCellSpacePartition
16:46:21: - - prevPosXZ: 125.66 123.899
16:46:21: UpdateEntity
16:46:21:  - OldIdx: 3871
16:46:21:  - NewIdx: 3871
16:46:21: -pCellSpacePartition done
16:46:21: -TerrainAdaption
16:46:21: -EnforceNonPenetrationConstraint
16:46:21: Unit done
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 3
16:46:21: UpdateUnits: Unit: 3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 2
16:46:21: - Neighbours in cell 1 push_back with id: 1
16:46:21: - Neighbours in cell 2 push_back with id: 0
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: pTarget == 0
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - FindPreferredEnemy!2
16:46:21: - FindPreferredEnemy!3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 2
16:46:21: - Neighbours in cell 1 push_back with id: 1
16:46:21: - Neighbours in cell 2 push_back with id: 0
16:46:21: - Neighbours in cell 3 push_back with id: 4
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - FindPreferredEnemy!4
16:46:21: - neighbourObjects element0
16:46:21: - - neighbourObjects go->id2
16:46:21: - neighbourObjects element1
16:46:21: - - neighbourObjects go->id1
16:46:21: - neighbourObjects element2
16:46:21: - - neighbourObjects go->id0
16:46:21: - neighbourObjects element3
16:46:21: - - neighbourObjects go->id4
16:46:21: - neighbourObjects element4
16:46:21: - - neighbourObjects go->id5
16:46:21: - neighbourObjects element5
16:46:21: - - neighbourObjects go->id7
16:46:21: - neighbourObjects element6
16:46:21: - - neighbourObjects go->id8
16:46:21: - neighbourObjects element7
16:46:21: - - neighbourObjects go->id10
16:46:21: - neighbourObjects element8
16:46:21: - - neighbourObjects go->id11
16:46:21: - neighbourObjects done!
16:46:21: - preferredEnemy != 0
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.7
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: Strike!
16:46:21: - in_unit.definition.strikeRadius is: 3
16:46:21: - targetUnit->definition.baseRadius is: 0.5
16:46:21: - unitCircle.Collides(targetCircle) is: false
16:46:21: - StrikerID is: 3
16:46:21: - TargetId is: 7
16:46:21: - rotationProgress is: 1.#INF
16:46:21: - Collides?
16:46:21: -UpdatePositionAndRotation
16:46:21: -pCellSpacePartition
16:46:21: - - prevPosXZ: 125.249 125.848
16:46:21: UpdateEntity
16:46:21:  - OldIdx: 3999
16:46:21:  - NewIdx: 3999
16:46:21: -pCellSpacePartition done
16:46:21: -TerrainAdaption
16:46:21: -EnforceNonPenetrationConstraint
16:46:21: Unit done
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 4
16:46:21: UpdateUnits: Unit: 4
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 1
16:46:21: - Neighbours in cell 3 push_back with id: 0
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: pTarget == 0
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - FindPreferredEnemy!2
16:46:21: - FindPreferredEnemy!3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 1
16:46:21: - Neighbours in cell 3 push_back with id: 0
16:46:21: - Neighbours in cell 4 push_back with id: 5
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - FindPreferredEnemy!4
16:46:21: - neighbourObjects element0
16:46:21: - - neighbourObjects go->id3
16:46:21: - neighbourObjects element1
16:46:21: - - neighbourObjects go->id2
16:46:21: - neighbourObjects element2
16:46:21: - - neighbourObjects go->id1
16:46:21: - neighbourObjects element3
16:46:21: - - neighbourObjects go->id0
16:46:21: - neighbourObjects element4
16:46:21: - - neighbourObjects go->id5
16:46:21: - neighbourObjects element5
16:46:21: - - neighbourObjects go->id7
16:46:21: - neighbourObjects element6
16:46:21: - - neighbourObjects go->id8
16:46:21: - neighbourObjects element7
16:46:21: - - neighbourObjects go->id10
16:46:21: - neighbourObjects element8
16:46:21: - - neighbourObjects go->id11
16:46:21: - neighbourObjects done!
16:46:21: - preferredEnemy != 0
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.7
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: Strike!
16:46:21: - in_unit.definition.strikeRadius is: 3
16:46:21: - targetUnit->definition.baseRadius is: 0.5
16:46:21: - unitCircle.Collides(targetCircle) is: false
16:46:21: - StrikerID is: 4
16:46:21: - TargetId is: 7
16:46:21: - rotationProgress is: 1.#INF
16:46:21: - Collides?
16:46:21: -UpdatePositionAndRotation
16:46:21: -pCellSpacePartition
16:46:21: - - prevPosXZ: 127.147 125.219
16:46:21: UpdateEntity
16:46:21:  - OldIdx: 3999
16:46:21:  - NewIdx: 3999
16:46:21: -pCellSpacePartition done
16:46:21: -TerrainAdaption
16:46:21: -EnforceNonPenetrationConstraint
16:46:21: Unit done
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 5
16:46:21: UpdateUnits: Unit: 5
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 1
16:46:21: - Neighbours in cell 3 push_back with id: 0
16:46:21: - Neighbours in cell 4 push_back with id: 4
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: - Update done
16:46:21: state. Unit: SoldierManager
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - FindPreferredEnemy!2
16:46:21: - FindPreferredEnemy!3
16:46:21: CalculateNeighbors
16:46:21: - Neighbours cleard, size(): 0
16:46:21: - Neighbours in cell 0 push_back with id: 3
16:46:21: - Neighbours in cell 1 push_back with id: 2
16:46:21: - Neighbours in cell 2 push_back with id: 1
16:46:21: - Neighbours in cell 3 push_back with id: 0
16:46:21: - Neighbours in cell 4 push_back with id: 4
16:46:21: - Neighbours in cell 5 push_back with id: 7
16:46:21: - Neighbours in cell 6 push_back with id: 8
16:46:21: - Neighbours in cell 7 push_back with id: 10
16:46:21: - Neighbours in cell 8 push_back with id: 11
16:46:21: - Neighbours done, size(): 9
16:46:21: - FindPreferredEnemy!4
16:46:21: - neighbourObjects element0
16:46:21: - - neighbourObjects go->id3
16:46:21: - neighbourObjects element1
16:46:21: - - neighbourObjects go->id2
16:46:21: - neighbourObjects element2
16:46:21: - - neighbourObjects go->id1
16:46:21: - neighbourObjects element3
16:46:21: - - neighbourObjects go->id0
16:46:21: - neighbourObjects element4
16:46:21: - - neighbourObjects go->id4
16:46:21: - neighbourObjects element5
16:46:21: - - neighbourObjects go->id7
16:46:21: - neighbourObjects element6
16:46:21: - - neighbourObjects go->id8
16:46:21: - neighbourObjects element7
16:46:21: - - neighbourObjects go->id10
16:46:21: - neighbourObjects element8
16:46:21: - - neighbourObjects go->id11
16:46:21: - neighbourObjects done!
16:46:21: - preferredEnemy != 0
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.7
16:46:21: - Update done
16:46:21: state. Unit: FindPreferredEnemy
16:46:21: FindPreferredEnemy!
16:46:21: - in_unit.GetTargetObjectId(targetId) is true.
16:46:21: - Update done
16:46:21: state. Unit: AttackTarget
16:46:21: GetTargetObjectId true
16:46:21: got pTarget
16:46:21: Strike!
16:46:21: - in_unit.definition.strikeRadius is: 3
16:46:21: - targetUnit->definition.baseRadius is: 0.5
16:46:21: - unitCircle.Collides(targetCircle) is: true
16:46:21: - StrikerID is: 5
16:46:21: - TargetId is: 7
16:46:21: - rotationProgress is: 1.#INF
16:46:21: - Collides?
16:46:21: - Collides!
16:46:21: - Thrust!
16:46:21: -UpdatePositionAndRotation
16:46:21: QUAT DELTA FAIL!!!
16:46:21: -pCellSpacePartition
16:46:21: - - prevPosXZ: 129.07 125.769
16:46:21: UpdateEntity
16:46:21:  - OldIdx: 4000
16:46:21:  - NewIdx: 4000
16:46:21: -pCellSpacePartition done
16:46:21: -TerrainAdaption
16:46:21: -EnforceNonPenetrationConstraint
16:46:21: Unit done
16:46:21: UpdateUnits with size: 12
16:46:21: UpdateUnits: Iterator value: 6
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: unordered_map for storing/removing game objects

Post by bstone »

Yes, you increment the invalidated iterator. That's a no-no since the incremented iterator picks up the pointer to the next node from the deleted node object and the result is unpredictable. The simplest fix would be:

Code: Select all

const UnitsType::iterator next = ++UnitsType::iterator( iter2 );

gameListener.objectMgr->units.erase( iter2 );

iter2 = next;
That should work with the boost::unordered_map<> implementation, at least in v1.48, but things like that are tricky - if their implementation changes in a way that will break the next iterator value as well then you're busted 8)
User avatar
Oceax
Gnoblar
Posts: 19
Joined: Wed Sep 10, 2008 4:14 pm

Re: unordered_map for storing/removing game objects

Post by Oceax »

Problem solved.
Even if you just try to access an element in unordered_map to look for an element, it will add a new key!! :x
This adds a new entry in unordered_map with key = in_key but without any object mapped to it. :roll:
Unit* ObjectManager::GetUnit(int in_key) { return units[in_key];}

In my case, the unit that had killed a unit in the last loop is now checking it's target, GetUnit(targetId).
It was suppose to conclude that this unit does not exists any more and look for another enemy but it added a new entry in units. :(

So i changed it to.
Unit* ObjectManager::GetUnit(int in_key)
{
Unit* returnObject;
try {

returnObject = ( units.at(in_key) );
}
catch ( std::out_of_range & e ){

//deal with exception
Ogre::LogManager::getSingleton().logMessage("GET UNIT FAILED!!! WITH in_key: " + Ogre::StringConverter::toString(in_key),LML_CRITICAL);
returnObject = 0;
}
return returnObject;
}

Access element
If k matches the key of an element in the container, the function returns a reference to its mapped value.

If k does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value. Notice that this always increases the container size by one, even if no mapped value is assigned to the element (the element is constructed using its default constructor).
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58

Re: [Solved] unordered_map for storing/removing game objects

Post by CABAListic »

Well, this is standard behaviour for maps, even for std::map. If you want to check if an element already exists, here's the standard way to do it (preferable to your try/catch hack):

Code: Select all

unordered_map<int,Unit*>::iterator iter = units.find(in_key);
if (iter != units.end())  // if element is not found in the map, the iterator will point to its end
  return iter->second;
else
  return 0;
User avatar
Oceax
Gnoblar
Posts: 19
Joined: Wed Sep 10, 2008 4:14 pm

Re: [Solved] unordered_map for storing/removing game objects

Post by Oceax »

Ok, that looks better.
Thanks!
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: [Solved] unordered_map for storing/removing game objects

Post by bstone »

Reading documentation is something that should be done, and done before pretty much anything else. Saves time and hair. :D
Boost Docs wrote: mapped_type& operator[](key_type const& k);

Effects: If the container does not already contain an elements with a key equivalent to k, inserts the value std::pair<key_type const, mapped_type>(k, mapped_type())
There's also the method at() which doesn't create new elements but throws if you access something that is not in the map, but that's just FYI - use find() as CABAListic showed you, that's the right way.