How to set and access later to another entity's property from an entity in Unity ECS?

336 Views Asked by At

I am trying to make a simple AI logic that has 3 states; Idle, Chase, Attack. In Idle state human entities should set their targets, in Chase state they will chase and ultimately Attack. I made it but with searching within double foreach loop and it isn't performant.

So I decided to hold a cache of all human's id's and LocalTransforms and set the target id to the targeter. This way I wanted to be able to get the target position with just positions[targetIndex].

  1. If I store the LocalTransforms in a BlobArray and set a target index for the target's LocalTransform into the targeter's property, LocalTransforms simply don't updating because they are being set only at the initialization when I assign the LocalTransforms.

  2. I tried to update the LocalTransform BlobArray in a job struct but simple I can't pass a BlobArray into the job struct (it says "InvalidOperationException: HumanFindTargetJob.JobData.arrayAspect.Value._Data uses unsafe Pointers which is not allowed.") and I don't want to make it on the main thread.

  3. I tried to do the things with SystemAPI.Query but I can't get a reference and send the query to the job and to get the query I must do it in a system.

  4. I tried to hold the properties in separate NativeArrays in a singleton centralized c# class but it is not compatible with the Burst complier.

Can you help me?

1

There are 1 best solutions below

0
On

Create separate IComponentData to hold distinct data, for example:

public struct HumanState : IComponentData
{
    public EHumanState Value;
}

public struct HumanTarget : IComponentData
{
    public Entity Value;
}

// etc.

then, to access target's position you can use GetComponentLookup<LocalTransform>:

[BurstCompile]
public void OnUpdate ( ref SystemState state )
{
    var transformData = SystemAPI.GetComponentLookup<LocalTransform>( isReadOnly:true );
            
    foreach( var (humanState,humanTarget,transform) in SystemAPI.Query<HumanState,HumanTarget,LocalTransform>() )
    {
        if( humanState.Value==EHumanState.Chasing )
        if( transformData.TryGetComponent(humanTarget.Value,out var targetTransform) )
        {
            float3 targetPos = targetTransform.Position;
            /* moves toward target position */
        }
    }
}