Debain 9, MonoDevelop 6.2 Stable, MonoGame 3.6, latest clone of Monogame.Extended.
Forewarning: I am only an intermediate programmer. Just enough to make me dangerous but nowhere near an expert.
I run EntityComponentSystem
inside of a game screen class. The game runs fine the first time around. If you quit the game screen and return to the main menu, then try to play again, this exception is thrown when EntityComponentSystem
is calling Scan(params Assembly[] assemblies)
, which calls CreateSystems(List systemTypeInfos, int componentCount)
and in turn EntityManager.FillComponentBits(andMask, aspectAttribute.Components)
. The exception is thrown inside of BitVector
(which is the andMask
). FillComponentBits
is trying to assign a value to the bool
indexer BitVector[int index]
property but the index is out of range and throws an exception.
EDIT: I set a break point and inspected the variables and the first time the index value of BitVector[int index]
was 26. The second time when the exception is thrown it’s 53. EDIT2: It’s pretty clear that the index value is being doubled.
Am I supposed to be resetting or destroying the EntityComponentSystem
some how when a game is quit, even if it’s just returning to the main menu? I assume this problem is happening because EntityComponentSystem
is trying to do something it’s already done. I’m sure you can imagine this creates a problem for a game intended to be fully featured and finished. This is just my guess though, I suppose I could be wrong. I tried to work around it but I was unsuccessful.
If you need more info on how I am managing the game states/screens, let me know.
Here’s the stack trace: https://pastebin.com/2PCL4Uv0
Thanks in advance!
Are you calling EntityComponentSystem.Scan
multiple times?
Not every frame. It’s being called once in the constructor of the game screen when the gameplay is started the first time. Quitting the game to the main menu and selecting play adds a new game screen where EntityComponentSystem
gets instantiated again in the game screen constructor. Apparently something isn’t getting deleted off the stack or heap and the same data is being added to the second time around. I’ll be trying to hunt it down.
Well, I think that is the problem. Scan
adds to the collections.
Any further help by someone who has encountered this before would be much appreciated.
I am slowly making progress:
BitVector
holds the component count in _array
.
EntityManager._componentTypes
holds a list of the component types.
This is essentially the same amount of items as BitVector._array
.
_componentTypes
is a dictionary where the values are EntityComponentTypes
which have an int Index
property. This property is supposed to correlate with the number of items in _componentTypes
.
During the first run, there are 27 items in _componentTypes
and the Index
properties of it’s EntityComponentTypes
range from 0-26.
On the second run, _componentTypes.Count
still only has 27 items.
The Index
properties of EntityComponentTypes
were added to which make the values 27-53.
When these values are passed into the BitVector
for a calculation it throws System.IndexOutOfRangeException
(the foreach
loops starts by passing 53.)
Because BitVector._array
was set to have indexes of 0-26 (27 items).
Now I just have to figure out why this is happening and how to fix it…hopefully a quick fix is just a matter of clearing some collections before registering components.
The problem happens in this method (a little stack trace for explanation.)
EntityManager.CreateComponentTypesFrom(List componentTypeInfos)
,
EntityComponentSystem.RegisterComponents(componentTypeInfos)
,
EntityComponentSystem.Scan(params Assembly[] assemblies)
The private static field EntityComponentType._nextIndex
is never set back to 0 probably because the EntityComponentSystem
in general was never meant to call Scan
twice in the same program.
Currently thinking about the best way to solve this.
Problem is solved by simply changing EntityComponentType._nextIndex
to a public property NextIndex
and setting it to 0 in EntityManager.CreateComponentTypesFrom(List componentTypeInfos)
. Not sure if that’s a bad idea or not, but it works.