The 0.1.0 patch notes mentioned:
However, when EntityManager is used inside a DynamicBuffer foreach
, I get the following error:
This is the code to reproduce:
using Unity.Entities;
public struct Tag : IComponentData
{
}
[InternalBufferCapacity(4)]
public struct BufferData : IBufferElementData
{
public float Value;
}
public class TestSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.ForEach((Entity entity, DynamicBuffer<BufferData> buffer) =>
{
foreach (BufferData bufferData in buffer)
{
if (!EntityManager.HasComponent<Tag>(entity))
{
EntityManager.AddComponentData(entity, new Tag());
}
}
});
}
}
The DynamicBuffer is filled with 4 values at entity conversion time. Is this error by design or a bug?
Singtaa
September 18, 2019, 4:27pm
2
Tested your code and can confirm. After the EntityManager.AddComponentData
, buffer
will be deallocated. Should be a bug.
For the time being, you’ll have to keep doing EntityManager.GetBuffer<BufferData>(entity)
after every structural change.
jeremies_unity:
The 0.1.0 patch notes mentioned:
However, when EntityManager is used inside a DynamicBuffer foreach
, I get the following error:
This is the code to reproduce:
using Unity.Entities;
public struct Tag : IComponentData
{
}
[InternalBufferCapacity(4)]
public struct BufferData : IBufferElementData
{
public float Value;
}
public class TestSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.ForEach((Entity entity, DynamicBuffer<BufferData> buffer) =>
{
foreach (BufferData bufferData in buffer)
{
if (!EntityManager.HasComponent<Tag>(entity))
{
EntityManager.AddComponentData(entity, new Tag());
}
}
});
}
}
The DynamicBuffer is filled with 4 values at entity conversion time. Is this error by design or a bug?
Can you update with bug report if you file one. I would love to track this
Rett
September 18, 2019, 8:31pm
5
Pretty sure this is by design.
DynamicBuffer is a pointer to an array (usually stored inline in the chunk). When you add the Tag component you move the entity and its components (including the array) to another archetype/chunk, but the pointer still points to the old location, so it is correctly recognized as invalid.
Could use a better error message I guess.
1 Like
But isn’t it the same with all EntityManager operations inside a ForEach? To me it’s weird that the new version handles only some of the chunk-altering methods.
Rett
September 18, 2019, 9:11pm
7
The new (post-0.1.0) ForEach is more or less:
var query = PrepareQuery();
var entities = query.ToEntityArray();
foreach (var entity in entities) {
var copy1 = GetComponent<SecondLambdaArg>(entity);
lambda(entity, ref copy1);
if (HasComponent<SecondLambdaArg>(entity)){
SetComponent(entity, copy1);
}
}
Entities are stable across structural changes and all their components are copied locally in the ForEach to make the ref stable.
1 Like
Singtaa
September 19, 2019, 2:06am
8
Rett:
The new (post-0.1.0) ForEach is more or less:
var query = PrepareQuery();
var entities = query.ToEntityArray();
foreach (var entity in entities) {
var copy1 = GetComponent<SecondLambdaArg>(entity);
lambda(entity, ref copy1);
if (HasComponent<SecondLambdaArg>(entity)){
SetComponent(entity, copy1);
}
}
Entities are stable across structural changes and all their components are copied locally in the ForEach to make the ref stable.
Okay that makes sense. For perf reasons, probably not a good idea to also copy buffers around.
farpini
September 19, 2019, 11:28am
9
I had the same issue and got that error today.
JPrzemieniecki is right, it’s an error by design.
You can copy the buffer to a NativeArray using buffer.ToNativeArray and keep your code design using the EntityManager inside the loop without errors.
Thanks everyone, this makes sense!