Hi everyone,
I have a system and I’m trying to convert it into a parallel job. I’m struggling for days now as I don’t manage to translate the query correctly.
This is the foreach query that works well:
foreach ((
RefRW<LocalTransform> localTransform,
RefRW<ShootAttack> shootAttack,
RefRO<Target> target,
RefRW<TargetPositionPathQueued> targetPositionPathQueued,
EnabledRefRW<TargetPositionPathQueued> targetPositionPathQueuedEnabled,
RefRW<UnitMover> unitMover,
Entity entity)
in SystemAPI.Query<
RefRW<LocalTransform>,
RefRW<ShootAttack>,
RefRO<Target>,
RefRW<TargetPositionPathQueued>,
EnabledRefRW<TargetPositionPathQueued>,
RefRW<UnitMover>>().WithDisabled<MoveOverride>().WithPresent<TargetPositionPathQueued>().WithEntityAccess())
and I’m trying to convert it in the job:
[BurstCompile]
//[WithDisabled(typeof(MoveOverride))]
public partial struct PositioningAttackJob : IJobEntity
{
public float deltaTime; // Store DeltaTime inside the job
[NativeDisableParallelForRestriction] public ComponentLookup<LocalTransform> localTransformComponentLookup;
//[ReadOnly] public NativeArray<MoveOverride> moveOverrideArray;
public void Execute(
RefRW<ShootAttack> shootAttack,
RefRO<Target> target,
RefRW<TargetPositionPathQueued> targetPositionPathQueued,
EnabledRefRW<TargetPositionPathQueued> targetPositionPathQueuedEnabled,
RefRW<UnitMover> unitMover,
EnabledRefRO<MoveOverride> moveOverrideEnabled, // Checks if MoveOverride is enabled
Entity entity)
{
// Only execute logic if MoveOverride is DISABLED
if (moveOverrideEnabled.ValueRO)
{
return;
}
Debug.Log("Entity: "+entity);
if (target.ValueRO.targetEntity == Entity.Null)
{
return;
}
}
I’m pretty sure the problem is because I fail to translate the WithDisabled into the job as I can see with debug that the job does not run continuously for my entities. While if I debug in the foreach query I can see it running continuously.
I really need help here as I’m stuck after trying all sorts of options.
Thank you
I could do it in IJobChunk:
public partial struct PositioningAttackSystem : ISystem
{
private EntityQuery query;
private EntityTypeHandle entityType;
private ComponentTypeHandle<Target> targetType;
private ComponentTypeHandle<TargetPositionPathQueued> pathQueuedType;
private ComponentTypeHandle<UnitMover> unitMoverType;
private ComponentTypeHandle<MoveOverride> moveOverrideType;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
this.query = new EntityQueryBuilder(Allocator.Temp)
.WithAll<LocalTransform>()
.WithAll<ShootAttack>()
.WithAll<Target>()
.WithAll<TargetPositionPathQueued>()
.WithAll<UnitMover>()
.WithDisabled<MoveOverride>()
.Build(ref state);
this.entityType = state.GetEntityTypeHandle();
this.targetType = state.GetComponentTypeHandle<Target>();
this.pathQueuedType = state.GetComponentTypeHandle<TargetPositionPathQueued>();
this.unitMoverType = state.GetComponentTypeHandle<UnitMover>();
this.moveOverrideType = state.GetComponentTypeHandle<MoveOverride>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
// Update handles
this.entityType.Update(ref state);
this.targetType.Update(ref state);
this.pathQueuedType.Update(ref state);
this.unitMoverType.Update(ref state);
this.moveOverrideType.Update(ref state);
PositioningAttackJob positioningAttackJob = new()
{
entityType = this.entityType,
targetType = this.targetType,
pathQueuedType = this.pathQueuedType,
unitMoverType = this.unitMoverType,
moveOverrideType = this.moveOverrideType,
};
state.Dependency = positioningAttackJob.ScheduleParallel(this.query, state.Dependency);
}
[BurstCompile]
private struct PositioningAttackJob : IJobChunk
{
public EntityTypeHandle entityType;
[ReadOnly]
public ComponentTypeHandle<Target> targetType;
public ComponentTypeHandle<TargetPositionPathQueued> pathQueuedType;
public ComponentTypeHandle<UnitMover> unitMoverType;
public ComponentTypeHandle<MoveOverride> moveOverrideType;
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
NativeArray<Entity> entities = chunk.GetNativeArray(entityType);
NativeArray<Target> targets = chunk.GetNativeArray(ref targetType);
NativeArray<TargetPositionPathQueued> pathQueueds = chunk.GetNativeArray(ref pathQueuedType);
NativeArray<UnitMover> unitMovers = chunk.GetNativeArray(ref unitMoverType);
NativeArray<MoveOverride> moveOverrides = chunk.GetNativeArray(ref moveOverrideType);
ChunkEntityEnumerator enumerator = new(useEnabledMask, chunkEnabledMask, chunk.Count);
while (enumerator.NextEntityIndex(out int i))
{
// You don't have to check for disabled since it was already done in the query
// All entities here have disabled MoveOverride
// To access target or any of the components that you need
Target target = targets[i];
}
}
}
}
Thank you Daven.
It’s not clear to me how can I afterwards reference for example the LocalTransform of target.entity with this structure.
Hope this can help.
public partial struct SampleSystem : ISystem
{
private EntityQuery _query;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
_query = SystemAPI.QueryBuilder()
.WithAllRW<LocalTransform>()
.WithAllRW<ShootAttack>()
.WithAllRW<UnitMover>()
.WithPresentRW<TargetPositionPathQueued>()
.WithAll<Target>()
.WithDisabled<MoveOverride>()
.Build();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Dependency = new SampleJob().ScheduleParallel(_query, state.Dependency);
}
private partial struct SampleJob : IJobEntity
{
private void Execute(
in Entity entity,
ref LocalTransform transform,
ref ShootAttack shootAttack,
ref UnitMover unitMover,
ref TargetPositionPathQueued targetPositionPathQueued,
EnabledRefRW<TargetPositionPathQueued> targetPositionPathQueuedEnabled,
in Target target
)
{
}
}
}
Tested with some entities produced by this authoring:
internal sealed class SampleAuthoring : MonoBehaviour
{
private class Baker : Baker<SampleAuthoring>
{
public override void Bake(SampleAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent<ShootAttack>(entity);
AddComponent<Target>(entity);
AddComponent<TargetPositionPathQueued>(entity);
AddComponent<UnitMover>(entity);
AddComponent<MoveOverride>(entity);
SetComponentEnabled<MoveOverride>(entity, false);
}
}
}
I used Unity 6000.0.35, Entities 1.3.9.
You need a ComponentLookup to the job. It’s like a dictionary of your entities to LocalTransform. You can use target.entity as the key to that.
Thank you Lais. It worked like that. So I need to use a query first and then add it to the job via state.dependency. My god how much time I wasted trying to figure the proper way.
Thank you and thank you @davenirline as well!