Information about separate entity in IJobChunk

Hey

I’m iterating over all entities which got “TriggerEnter” component attached (component acts as event, it will be removed at the end of frame)
In that component I have trigger entity we collided with.

In the job I want to check if that entity has some kind of component (“Flamed” in my case) and if it does, then continue our job and change data on our “local” entity.

What approach can you suggest?

I was thinking about pushing that information to the “TriggerEnter” component, but as features add that component would inflate too much.
Second Idea was to store archetype of trigger entity into “TriggerEnter” component, but I was not able to find the way to get it.

JobSystem

using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;

[UpdateAfter(typeof(PhysicsEventEmissionBarrier))]
public class AddHeatingSystem : JobComponentSystem
{
    private ComponentGroup _query;

protected override void OnCreateManager()
{
    _query = GetComponentGroup(new EntityArchetypeQuery
    {
        All  = new[] {ComponentType.ReadOnly<TriggerEnter>(), ComponentType.ReadOnly<Flamable>()},
        None = Array.Empty<ComponentType>(),
        Any  = Array.Empty<ComponentType>()
    }, new EntityArchetypeQuery
    {
        All  = new[] {ComponentType.ReadOnly<TriggerEnter>(), ComponentType.ReadOnly<Flamable>(), ComponentType.Create<Heating>()},
        None = Array.Empty<ComponentType>(),
        Any  = Array.Empty<ComponentType>()
    });
}

    private struct AddHeating : IJobChunk
    {
        public EntityCommandBuffer.Concurrent Commands;

        public            ArchetypeChunkEntityType                  EntityType;
        [ReadOnly] public ArchetypeChunkComponentType<TriggerEnter> TriggerEnterType;
        public            ArchetypeChunkComponentType<Heating>      HeatingType;

        public void Execute(ArchetypeChunk chunk, int chunkIndex)
        {
            var entityArray  = chunk.GetNativeArray(EntityType);
            var triggerArray = chunk.GetNativeArray(TriggerEnterType);
            var heatArray    = chunk.GetNativeArray(HeatingType);

            var hasHeat = heatArray.Length > 0;

            for (int i = 0; i < triggerArray.Length; i++)
            {
                var triggerEntity = triggerArray[i].Trigger;

                *****************
                //IF TRIGGER ENTITY HAS COMPONENT "FLAMED", then do work
                if (!triggerEntity.HasComponent<Flamed>)
                    continue;
                ******************

                if (hasHeat)
                {
                    //increment counter
                }
                else
                {
                    //add Heating with value of 1
                }
            }
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        return new AddHeating
        {
            EntityType       = GetArchetypeChunkEntityType(),
            TriggerEnterType = GetArchetypeChunkComponentType<TriggerEnter>(),
            HeatingType      = GetArchetypeChunkComponentType<Heating>()
        }.Schedule(_query, inputDeps);
    }
}

All custom data types

using System;
using Unity.Entities;

[Serializable]
public struct Flamable : IComponentData
{
    //Min temperature to be flamed
    public float Temperature;
}
public struct Flamed : IComponentData{}

[Serializable]
public struct Temperature : IComponentData
{
    public float Value;
}

public struct Heating : IComponentData
{
    //Amount ot heat sources infuencing that entity
    public int Count;
}

[UpdateBefore(typeof(EndFrameBarrier))]
public class PhysicsEventRemoveBarrier : BarrierSystem{}

[UpdateBefore(typeof(PhysicsEventRemoveBarrier))]
public class PhysicsEventEmissionBarrier : BarrierSystem{}

public struct TriggerEnter : IComponentData
{
    public Entity Trigger;
}

public struct TriggerExit : IComponentData
{
    public Entity Trigger;
}

public struct CollisionEnter : IComponentData
{
    public Entity Trigger;
    public float3 Position;
    public float3 Normal;
}

public struct CollisionExit : IComponentData
{
    public Entity Trigger;
}

Couldn’t you just use: ComponentDataFromEntity<Flamed>.Exists(triggerEntity)

EDIT: Fixed syntax.

1 Like

Thanks, it looks exactly like what I want.

But when I put it into jobs - it doesn’t work. It’s not clear from the docs where it should be placed…

using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Jobs;

[UpdateAfter(typeof(PhysicsEventEmissionBarrier))]
public class AddHeatingSystem : JobComponentSystem
{
    private ComponentGroup _query;

    protected override void OnCreateManager()
    {
        _query = GetComponentGroup(new EntityArchetypeQuery
        {
            All  = new[] {ComponentType.ReadOnly<TriggerEnter>(), ComponentType.ReadOnly<Flamable>()},
            None = Array.Empty<ComponentType>(),
            Any  = Array.Empty<ComponentType>()
        }, new EntityArchetypeQuery
        {
            All  = new[] {ComponentType.ReadOnly<TriggerEnter>(), ComponentType.ReadOnly<Flamable>(), ComponentType.Create<Heating>()},
            None = Array.Empty<ComponentType>(),
            Any  = Array.Empty<ComponentType>()
        });
    }

    private struct AddHeating : IJobChunk
    {
        public EntityCommandBuffer.Concurrent Commands;

        [ReadOnly] public            ArchetypeChunkEntityType                  EntityType;
        [ReadOnly] public ArchetypeChunkComponentType<TriggerEnter> TriggerEnterType;
        public            ArchetypeChunkComponentType<Heating>      HeatingType;
     
        [NativeSetThreadIndex] private int _threadIndex;
     
        [ReadOnly] [Inject] private ComponentDataFromEntity<Flamed> _flamedEntities;

        public void Execute(ArchetypeChunk chunk, int chunkIndex)
        {
            var entityArray  = chunk.GetNativeArray(EntityType);
            var triggerArray = chunk.GetNativeArray(TriggerEnterType);
            var heatArray    = chunk.GetNativeArray(HeatingType);

            var hasHeat = heatArray.Length > 0;

            for (int i = 0; i < triggerArray.Length; i++)
            {
                var entity = entityArray[i];
                var triggerEntity = triggerArray[i].Trigger;

                if (_flamedEntities.Exists(triggerEntity))
                {
                    if (hasHeat)
                    {
                        var heat = heatArray[i];
                        heat.Count++;
                        Commands.SetComponent(_threadIndex, entity, heat);
                    }
                    else
                    {
                        Commands.AddComponent(_threadIndex, entity, new Heating{Count = 1});
                    }
                }
            }
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        return new AddHeating
        {
            EntityType       = GetArchetypeChunkEntityType(),
            TriggerEnterType = GetArchetypeChunkComponentType<TriggerEnter>(),
            HeatingType      = GetArchetypeChunkComponentType<Heating>()
        }.Schedule(_query, inputDeps);
    }
}

Alright, looks like I need to
Write this in System:

[ReadOnly] [Inject] public ComponentDataFromEntity<Flamed> FlamedEntities;

And pass it to Job in OnUpdate by hand

Correct. There should also be a GetComponentDataFromEntity method in the ComponentSystem class that you can call in Update().

1 Like