[Bug] Add/Remove component and Destroy entity cause LastChunk error
Sarofc opened this issue · 6 comments
Reproduce: add DestroyForloop to WorldTest.cs
Result: System.IndexOutOfRangeException : Index was outside the bounds of the array.
[Test]
public void DestroyForloop()
{
var _entitiesToChangeColor = new QueryDescription().WithAll<Transform>();
var entities = new List<Entity>();
const int len = 1000;
for (int i = 0; i < len; i++)
{
var ent = _world.Create(_entityGroup);
entities.Add(ent);
}
for (int i = 8; i < entities.Count; i++)
{
var ent = entities[i];
if (i % 3 == 0)
{
// A demonstration of bulk adding and removing components.
_world.Add(in _entitiesToChangeColor, 1);
_world.Remove<int>(in _entitiesToChangeColor);
_world.Destroy(ent);
}
}
}
Thanks! Ill look into this soon :)
Fixed, lemme know if it worked! :)
Not released as a nugget yet, but on the master haha
No its not fixed yet, dammit. My mistake
I'm seeing what might be a similar crash on 1.2.7 alpha. When adding, removing components and destroying and creating new entities, I get an out of index exception. Looking at the debugger, I see this, with chunk capacity and size at 250.
Adding an empty component (a struct with no params) causes an IndexOutsideOfBoundsException
Edit - a few more details:
- All tag components were removed using world.Remove, querying just for that tag.
- This is the first entity to be tagged after.
- The entity appears in the new archetype, but it doesn't have the new tag component under its component, perhaps because the execution through an exception partway through. There are no other entities.
- The exception:
System.IndexOutOfRangeException
HResult=0x80131508
Message=Index was outside the bounds of the array.
Source=Arch
StackTrace:
at Arch.Core.Extensions.EntityExtensions.Add[T](Entity& entity, T& component) in C:\Users\Lars\RiderProjects\Arch\src\Arch\Core\Extensions\EntityExtensions.cs:line 206
- It occurs using World directly (World.Add) and extension method (Entity.Add)
Name | Value | Type | |
---|---|---|---|
◢ | Chunk | {Chunk = { Capacity = 250, Size = 250 }} | Arch.Core.Chunk |
Capacity | 250 | int | |
▶ ComponentIdToArrayIndex | {int[20]} | int[] | |
▶ Components | {System.Array[7]} | System.Array[] | |
▶ Entities | {Arch.Core.Entity[250]} | Arch.Core.Entity[] | |
Size | 250 | int | |
▶ | Components | {object[7]} | object[] |
▶ | EntityInfo | {Arch.Core.EntityInfo} | Arch.Core.EntityInfo |
Id | 2026 | int | |
IsAlive | true | bool | |
Version | 1 | int | |
▶ | World | {World { Id = 0, Capacity = 15182, Size = 1672 }} | Arch.Core.World |
Archetype
Name | Value | Type | |
---|---|---|---|
Capacity | 2 | int | |
ChunkSize | 16000 | int | |
◢ | Chunks | {Arch.Core.Chunk[16]} | Arch.Core.Chunk[] |
◢ [0] | {Chunk = { Capacity = 250, Size = 1 }} | Arch.Core.Chunk | |
Capacity | 250 | int | |
▶ ComponentIdToArrayIndex | {int[20]} | int[] | |
▶ Components | {System.Array[8]} | System.Array[] | |
▶ Entities | {Arch.Core.Entity[250]} | Arch.Core.Entity[] | |
Size | 1 | int | |
▶ [1] | {Chunk = { Capacity = 250, Size = 0 }} | Arch.Core.Chunk | |
Entity in that archetype, with 7 components instead of 8.
Name | Value | Type | |
---|---|---|---|
◢ | [0] | {Entity = { Id = 126, WorldId = 0 }} | Arch.Core.Entity |
▶ Archetype | {Archetype { Types = { ... }, BitSet = { _bits: 00000000000010000000000011011110,00000000000000000000000000000000,00000000000000000000000000000000,00000000000000000000000000000000,00000000000000000000000000000000,00000000000000000000000000000000,00000000000000000000000000000000,00000000000000000000000000000000, Length: 8 }, EntitiesPerChunk = 250, ChunkSize = 16000, Capacity = 5, Size = 5, Entities = 1000 }} | Arch.Core.Archetype | |
◢ Chunk | {Chunk = { Capacity = 250, Size = 250 }} | Arch.Core.Chunk | |
Capacity | 250 | int | |
▶ ComponentIdToArrayIndex | {int[20]} | int[] | |
▶ Components | {System.Array[7]} | System.Array[] | |
▶ Entities | {Arch.Core.Entity[250]} | Arch.Core.Entity[] | |
Size | 250 | int | |
▶ Components | {object[7]} | object[] | |
▶ EntityInfo | {Arch.Core.EntityInfo} | Arch.Core.EntityInfo | |
Id | 126 | int | |
IsAlive | true | bool | |
Version | 1 | int | |
▶ World | {World { Id = 0, Capacity = 11627, Size = 2060 }} | Arch.Core.World | |
▶ Raw View |
I think something else is going on in my case. I'll work on opening another bug.
I noticed that the byte size of the types was an even number before the archetype change, and an odd number after addition.
The entity that experiences the IndexOutsideOfBounds has 59 bytes in the archetype. This is because empty structs take 1 byte.
Originally, the entity had 7 components totaling 58 bytes. Adding one more 1 byte component would throw an index out of range sometimes.
I padded some structs to 2 byte. Ironically I missed one. But now it is 59 bytes before, and adding a 2 byte component makes it 61 bytes. It no longer throws an index outside of range exception, or at least I cannot reproduce it now.
Edit - never mind, was able to reproduce...
I'll keep looking at this as I think this is a different bug than this one.
I am trying with the latest master, and I am not seeing the crash but will continue to test.