Hi, i made this pattern for 3D Quadrant System to avoid looping through all entities for each entity
The problem this pattern makes EndSimulationEntityCommandBufferSystem >>Wait For Job Group Id>> very high for 1000 Entities
Why does it get so high even though with Burst and Scheduling?
is is there a better way to do this?
maybe a better way to group entities instead of changing Queries ?
i have two Systems,
1- adding and removing tag and Depending on the Coordinates, so it changing Queries
2- looping in Queries (by tags) and finding target by distance
As follows:
system 1 :
public class QueriesSystem : JobComponentSystem
{
public float time;
protected EndSimulationEntityCommandBufferSystem m_EndSimulationEcbSystem;
protected override void OnCreate()
{
base.OnCreate();
m_EndSimulationEcbSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var ecb = m_EndSimulationEcbSystem.CreateCommandBuffer().ToConcurrent();
float deltaTime = Time.DeltaTime;
JobHandle jobhandle = Entities.ForEach((Entity entity, int entityInQueryIndex,ref Place place, in Translation translation) =>
{
if (translation.Value.x > 0 && translation.Value.x < 1 && translation.Value.y > 0 && translation.Value.y < 1&& translation.Value.z > 0 && translation.Value.z < 1)
{
place.preplace = place.curplace;
place.curplace = 0;
if (place.curplace != place.preplace)
{
switch (place.prevplace)
{
case 0:
ecb.RemoveComponent<RedBoxTag>(entityInQueryIndex, entity);
break;
case 1:
ecb.RemoveComponent<GreenBoxTag>(entityInQueryIndex, entity);
break;
ETC....
}
ecb.AddComponent(entityInQueryIndex, entity, new RedBoxTag());
}
}
else if (translation.Value.x > 0 && translation.Value.x < 1 && translation.Value.y > 0 && translation.Value.y < 1 && translation.Value.z > 1 && translation.Value.z < 2)
{
place.preplace = place.curplace;
place.curplace = 1;
switch (place.prevplace)
{
case 0:
ecb.RemoveComponent<RedBoxTag>(entityInQueryIndex, entity);
break;
case 1:
ecb.RemoveComponent<GreenBoxTag>(entityInQueryIndex, entity);
break;
}
ecb.AddComponent(entityInQueryIndex, entity, new GreenBoxTag());
}
else if (ETC...)
{
ETC...
}
}).Schedule(inputDeps);
m_EndSimulationEcbSystem.AddJobHandleForProducer(jobhandle);
return jobhandle;
}
}
system 2 :
public class loopSystem : JobComponentSystem
{
protected EndSimulationEntityCommandBufferSystem m_EndSimulationEcbSystem;
EntityQuery triggers;
protected override void OnCreate()
{
base.OnCreate();
m_EndSimulationEcbSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var GreenBoxTags = GetEntityQuery(ComponentType.ReadOnly<GreenBoxTag>());
var RedBoxTags = GetEntityQuery(ComponentType.ReadOnly<RedBoxTag>());
NativeArray<Entity> GreenBoxTagsAR = GreenBoxTags.ToEntityArray(Allocator.TempJob);
NativeArray<Entity> RedBoxTagsAR = RedBoxTags.ToEntityArray(Allocator.TempJob);
ComponentDataFromEntity<Translation> translationsFE = GetComponentDataFromEntity<Translation>(true);
JobHandle jobhandle = Entities.WithAny<AntTag, QueenTag>().WithDeallocateOnJobCompletion(GreenBoxTagsAR).WithDeallocateOnJobCompletion(RedBoxTagsAR).ForEach((Entity entity, int entityInQueryIndex,in Place place) =>
{
switch (place.curplace)
{
case 0:
for (int i = 0; i < RedBoxTagsAR.Length; i++)
{
Entity trigentity = RedBoxTagsAR[i];
float3 pos = translationsFE[trigentity].Value;
float distance = math.distance(translationsFE[entity].Value, pos);
if (distance >= 0.1 && distance <= 0.5)
{
}
break;
case 1:
for (int i = 0; i < GreenBoxTagsAR.Length; i++)
{
Entity trigentity = GreenBoxTagsAR[i];
float3 pos = translationsFE[trigentity].Value;
float distance = math.distance(translationsFE[entity].Value, pos);
if (distance >= 0.1 && distance <= 0.5)
{
}
break;
case 2:
ETC...
break;
}
}).Schedule(inputDeps);
m_EndSimulationEcbSystem.AddJobHandleForProducer(jobhandle);
return jobhandle;
}
}
Using a Native Container storing entity references can offer you a much higher resolution grid without the cost of moving entities around. A higher resolution grid allows for far fewer checks in your loop, which will drastically outweigh the additional random access cost.
DreamingImLatios Sounds good thanks !
How can I use Native Container to storing entity, is it like a system that inserts entities by their positions into arrays inside IComponentData or IBufferElementData ? or how ?
brunocoimbra I triedISharedComponentData and I got a better performance, but there is a wierd problem when i start the game with just 3 entities the arrays t0ar.Length and t1ar.Length become about 50 ,I think there is a duplicate copies for this 3 entity inside the arrays, also i’m not sure if i’m using filters in right way, please can you tell me what am I doing wrong?
updated code :
public class QueriesSystem : JobComponentSystem
{
public float time;
protected EndSimulationEntityCommandBufferSystem m_EndSimulationEcbSystem;
protected override void OnCreate()
{
base.OnCreate();
m_EndSimulationEcbSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var ecb = m_EndSimulationEcbSystem.CreateCommandBuffer().ToConcurrent();
float deltaTime = Time.DeltaTime;
JobHandle jobhandle = Entities.ForEach((Entity entity, int entityInQueryIndex, ref Place place, in Translation translation) =>
{
if (translation.Value.x > 0 && translation.Value.x < 1 && translation.Value.y > 0 && translation.Value.y < 1 && translation.Value.z > 0 && translation.Value.z < 1)
{
place.preplace = place.curplace;
place.curplace = 0;
if (place.curplace != place.preplace)
{
ecb.SetSharedComponent(entityInQueryIndex, entity, new QuadrantISharedComponent { T = 0 });
}
}
else if (translation.Value.x > 0 && translation.Value.x < 1 && translation.Value.y > 0 && translation.Value.y < 1 && translation.Value.z > 1 && translation.Value.z < 2)
{
place.preplace = place.curplace;
place.curplace = 1;
if (place.curplace != place.preplace)
{
ecb.SetSharedComponent(entityInQueryIndex, entity, new QuadrantISharedComponent { T = 1 });
}
}
else if (ETC...)
{
ETC...
}
}).Schedule(inputDeps);
m_EndSimulationEcbSystem.AddJobHandleForProducer(jobhandle);
return jobhandle;
}
}
system 2 :
public class loopSystem : JobComponentSystem
{
protected EndSimulationEntityCommandBufferSystem m_EndSimulationEcbSystem;
EntityQuery triggers;
protected override void OnCreate()
{
base.OnCreate();
m_EndSimulationEcbSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var triggers = GetEntityQuery(typeof(QuadrantISharedComponent));
triggers.SetSharedComponentFilter(new QuadrantISharedComponent { T = 0 });
NativeArray<Entity> t0ar = triggers.ToEntityArray(Allocator.TempJob);
triggers.SetChangedVersionFilter(typeof(QuadrantISharedComponent));
triggers.SetSharedComponentFilter(new QuadrantISharedComponent { T = 1 });
NativeArray<Entity> t1ar = triggers.ToEntityArray(Allocator.TempJob);
ComponentDataFromEntity<Translation> translationsFE = GetComponentDataFromEntity<Translation>(true);
JobHandle jobhandle = Entities.WithAny<AntTag, QueenTag>().WithDeallocateOnJobCompletion(GreenBoxTagsAR).WithDeallocateOnJobCompletion(RedBoxTagsAR).ForEach((Entity entity, int entityInQueryIndex, in Place place) =>
{
switch (place.curplace)
{
case 0:
for (int i = 0; i < t0ar.Length; i++)
{
Entity trigentity = t0ar[i];
float3 pos = translationsFE[trigentity].Value;
float distance = math.distance(translationsFE[entity].Value, pos);
if (distance >= 0.1 && distance <= 0.5)
{
}
break;
case 1:
for (int i = 0; i < t1ar.Length; i++)
{
Entity trigentity = t1ar[i];
float3 pos = translationsFE[trigentity].Value;
float distance = math.distance(translationsFE[entity].Value, pos);
if (distance >= 0.1 && distance <= 0.5)
{
}
break;
case 2:
ETC...
break;
}
}).Schedule(inputDeps);
m_EndSimulationEcbSystem.AddJobHandleForProducer(jobhandle);
return jobhandle;
}
}
Seems like you are using in the right way, if you have only 3 entities and there is 50 in the entity array then there is something clearly wrong there… did you double to check to verify if that’s the actual case?
I am not sure if there is a built-in method for that, but you can create a third native array to put the combination by simply creating a new NativeArray with the size being the sum of both arrays sizes and then filling this array with the values.
WAYN_Group oh sorry i’m not sure what do you mean can you show me an example! , my goal here is to get a Native Array containing Entities of two Queries, the only way I know so far is to manually insert the entities from two arrays into a third native array as Brunocoimbra mentioned
@Michelle_Ca , sorry I got confused with the combination of 2 entity query derscriptions.
var query0 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationQuaternion)}
};
var query1 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationSpeed)}
};
EntityQuery m_Group = GetEntityQuery(new EntityQueryDesc[] {query0, query1});