Get Translation component of target entity in job

My entity “a” has component Target, that contains Entity “b”. In job im trying to get Translation component of entity “b” and change Translation component of entity “a” to follow them.
That is my code:

public class FollowSystem : SystemBase
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        var allTranslations = GetComponentDataFromEntity<Translation>(true);
        Entities.
            WithReadOnly(allTranslations).
            ForEach((Entity entity, ref Translation translation, in FollowEntity followEntity, in MovementSpeed movementSpeed) =>
        {
            if (!allTranslations.HasComponent(followEntity.Entity)) { return; }
            var targetPosition = allTranslations[followEntity.Entity].Value;
            var toTarget = targetPosition - translation.Value;
            if (math.length(toTarget) <= followEntity.Distance) { return; }
            var moveStep = math.normalize(toTarget) * movementSpeed.Value * dt;
            translation.Value += moveStep;
        }).ScheduleParallel();
    }
}

In that case i got error:
Error

InvalidOperationException: The writeable ComponentTypeHandle<Unity.Transforms.Translation> OnUpdate_LambdaJob0.JobData._lambdaParameterValueProviders.forParameter_translation._typeHandle is the same ComponentDataFromEntity<Unity.Transforms.Translation> as OnUpdate_LambdaJob0.JobData.allTranslations, two containers may not be the same (aliasing).
Unity.Entities.JobChunkExtensions.FinalizeScheduleChecked (System.Boolean isParallel, System.Int32 unfilteredChunkCount, Unity.Jobs.JobHandle prefilterHandle, Unity.Collections.NativeArray`1[T] prefilterData, System.Void* deferredCountData, System.Boolean useFiltering, Unity.Jobs.LowLevel.Unsafe.JobsUtility+JobScheduleParameters& scheduleParams, System.Boolean& executed, Unity.Jobs.JobHandle& result) (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobChunk.cs:270)
Unity.Entities.JobChunkExtensions.ScheduleInternal[T] (T& jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode, System.Boolean isParallel) (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobChunk.cs:246)
Unity.Entities.JobChunkExtensions.ScheduleParallel[T] (T jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobChunk.cs:150)
FollowSystem.OnUpdate () (at Assets/Scripts/Systems/FollowSystem.cs:11)
Unity.Entities.SystemBase.Update () (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/SystemBase.cs:412)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/ComponentSystemGroup.cs:472)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/ComponentSystemGroup.cs:477)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/ComponentSystemGroup.cs:417)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/ComponentSystem.cs:114)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/ScriptBehaviourUpdateOrder.cs:333)

Maby i gonna get translation some other way?

You can’t have both all translation and ref Translation. They represent the same data you are accessing at the same time as read only and read/write.
You should either have all translation as read write and work on a single thread or keep it as read only and set the translation through command buffer.

1 Like

The Transform System of Unity basically deals with this by having a Translation Component that writes to LocalToWorld which is the actual Position of the Entity. So one solution in this case is to Read from LocalToWorld.Position of your target and write to Translation of your Entity that is following.

1 Like

Thanx, now my code works!

public class FollowSystem : SystemBase
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        var ltw = GetComponentDataFromEntity<LocalToWorld>(true);

        Entities.
            WithReadOnly(ltw).
            ForEach((Entity entity, ref Translation translation, in FollowEntity followEntity, in MovementSpeed ms) =>
        {
            if (!ltw.HasComponent(followEntity.Entity)) { return; }
            var targetPosition = ltw[followEntity.Entity].Position;
            var toTarget = targetPosition - translation.Value;
            if (math.length(toTarget) <= followEntity.Distance) { return; }
            var moveStep = math.normalize(toTarget) * ms.Value * dt;
            translation.Value += moveStep;
        }).ScheduleParallel();
    }
}
1 Like