Problems with IJobParralelFor (Vector is not written)

Hi,
I try my best with DOTS and the Job System. But today I came to a Problem that I dont know what I do wrong.
What I want to do:
I have more then 1 Player and Many Many Units. I want to Calculate for the Units what target they should choose to Attack.

If the player gets near it should attack the player else just do nothing.

My Problem is this codeline:

sheepTarget[index] = new Target { target = player[i].Value };
                            Debug.Log("test" + player[i].Value);

Debug Log shows the right Vector.
But Target is not overritten. It just stays the same for every Sheep.

I’m no expert in C# and refs. I know what i want to do but i cant tell the code to do it :slight_smile:

Btw. How can i just save a Ref to a Vector not the Vector itself in a struct?

Here is my Job:

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using UnityEngine.Jobs;

namespace DefenceGame {
    public class AttackTargetSystem : JobComponentSystem {
        EntityQuery m_Group;
        EntityQuery m2_Group;
        protected override void OnCreate() {
            var query1 = new EntityQueryDesc {
                All = new ComponentType[] {ComponentType.ReadOnly<Translation>(),
                              ComponentType.ReadOnly<Sheep>(),
                              ComponentType.ReadOnly<Target>()}
            };
            var query2 = new EntityQueryDesc {
                All = new ComponentType[]{ ComponentType.ReadOnly<Translation>(),
                              ComponentType.ReadOnly<Player>()}
            };

            m_Group = GetEntityQuery(query1);
            m2_Group = GetEntityQuery(query2);
        }

        [BurstCompile]
        struct FindTargetJob : IJobParallelFor {
            [ReadOnly]
            public NativeArray<Translation> sheep;
            public NativeArray<Target> sheepTarget;
            [ReadOnly]
            public NativeArray<Translation> player;
            [ReadOnly]
            public Vector3 baseVector;

            public void Execute(int index) {

                for (int i = 0; i < player.Length; i++) {
                    if (Vector3.Distance(player[i].Value, sheep[index].Value) < 5f)
                        if (Vector3.Distance(sheep[index].Value, baseVector) > Vector3.Distance(player[i].Value, sheep[index].Value)) {
                            sheepTarget[index] = new Target { target = player[i].Value };
                            Debug.Log("test" + player[i].Value);
                        }
                }

            }
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps) {
            var sheepsTranslation = m_Group.ToComponentDataArray<Translation>(Allocator.TempJob);
            var sheepsTarget = m_Group.ToComponentDataArray<Target>(Allocator.TempJob);
            var sheepsBase = m_Group.ToComponentDataArray<Sheep>(Allocator.TempJob);
            var player = m2_Group.ToComponentDataArray<Translation>(Allocator.TempJob);

            var job = new FindTargetJob() { sheep = sheepsTranslation, sheepTarget = sheepsTarget, player = player, baseVector = sheepsBase[0].baseToAttack };
            JobHandle handle = job.Schedule(sheepsTranslation.Length, 64);
            handle.Complete();
            sheepsTranslation.Dispose();
            sheepsTarget.Dispose();
            sheepsBase.Dispose();
            player.Dispose();
            return handle;
        }
    }
}
using Unity.Entities;
using UnityEngine;

namespace DefenceGame {
    public struct Target : IComponentData {

        public Vector3 target;

    }
}
using Unity.Entities;
using UnityEngine;

namespace DefenceGame {
    public struct Sheep : IComponentData {
        public float randomNumber;
        public int entityIndex;

        public Vector3 baseToAttack;
    }
}
using Unity.Entities;
using UnityEngine;

namespace DefenceGame {
    public struct Player : IComponentData {

    }
}

You should copy back your array to entity query. ToComponentDataArray() → modification → CopyFromComponentDataArray()

https://docs.unity3d.com/Packages/com.unity.entities@0.3/api/Unity.Entities.EntityQuery.html#Unity_Entities_EntityQuery_CopyFromComponentDataArray__1_NativeArray___0__

Yeah That worked.
Here the Line for the People out there

            m_Group.CopyFromComponentDataArray(sheepsTarget);

I have another Question: . How can i just save a Ref to a Vector not the Vector itself in a struct?
I dont want to save a new Position every Frame. I want to save the ref. Is that possible?

In ECS you would remember the Entity that contains the vector, then later use ComponentDataFromEntity to emulate following the pointer.

How is the Performance from ComponentDataFromEntity?
Like if I have 5k Units and have to call ComponentDataFromEntity from every Entitie, does it make any Problems?

For my Case I want to set the Entitie as Target and if the Target is the same in the upper Code then dont Calculate the Distance and go to next Unit

CDFE is O(1) since Entity is like a fixed array index. You go there instantly.

Now that would mean very fast in OOP. However in data-oriented we care more, it is random memory access. Each time you can bring any new memory area to the cache potentially for at least the size of cache line.

Then you can picture how your cache would look like. It can jump anywhere technically, but if you know all your 5000 are linear in the same chunk then it would be still fast even if you randomly jump from index 37 435 622 then back to 50 for example as long as you work on the same component it would end up using what you have already brought in eventually, they would not be wasted.

e.g. you have one kind of CDFE and consecutively use it until you are done, with entities given from EQ.GetEntityArray and you are working with components from the same EQ.