Search Unity

Linking entities together for a system

Discussion in 'Entity Component System' started by distantcam, May 11, 2018.

  1. distantcam

    distantcam

    Joined:
    Jun 20, 2015
    Posts:
    4
    Let's say I have a follow system that updates an entities position based on another entities position, with some lag.

    How do I link the 2 entities together? How would I write a system like that?
     
  2. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    pseudocode:
    Code (CSharp):
    1. public struct Follow : IComponentData {
    2.     public Entity target;
    3.     // other attributes as needed, e.g. delay, distance, etc...
    4. }
    5.  
    6. public class FollowSystem : [Job]ComponentSystem {
    7.     // either
    8.     struct Group {
    9.         ComponentDataArray<Follow> follow;
    10.         ComponentDataArray<Position> position;
    11.     }
    12.     [Inject] Group group;
    13.     [Inject] ComponentDataFromEntity<Position> targetPositions;
    14.     // alternative:
    15.     struct Job : IJobProcessComponentData<Follow, Position> {
    16.         ComponentDataFromEntity<Position> positions
    17.         void Execute([ReadOnly] ref Follow follow, ref Position position) {
    18.             var targetPos = positions[follow.target];
    19.             // write your logic here...
    20.         }
    21.     }
    22. }
    your logic may depend on your needs:
    for each entity in group:
    1) fetch target position
    2) calculate distance
    3) move entity towards target according to your rule, e.g.:
    - Lerp (currentPos, targetPos, xxx)
    - if (distance > xxx) move towards target by difference
    - whatever else you want...
     
  3. distantcam

    distantcam

    Joined:
    Jun 20, 2015
    Posts:
    4
    Based on M_R's answer I got something working.

    Code (CSharp):
    1. [Serializable]
    2. public struct Follow : IComponentData
    3. {
    4.     public float Smoothing;
    5.     public Entity Target;
    6. }
    7.  
    8. public class FollowComponent : ComponentDataWrapper<Follow> { }
    9.  
    10. public class FollowSystem : JobComponentSystem
    11. {
    12.     [ComputeJobOptimization]
    13.     public struct Job : IJobParallelForTransform
    14.     {
    15.         [ReadOnly] private ComponentDataFromEntity<Position2D> position;
    16.         [ReadOnly] private ComponentDataArray<Follow> follow;
    17.  
    18.         public Job(ComponentGroup group, ComponentDataFromEntity<Position2D> position)
    19.         {
    20.             follow = group.GetComponentDataArray<Follow>();
    21.             this.position = position;
    22.         }
    23.  
    24.         public void Execute(int index, TransformAccess transform)
    25.         {
    26.             var scale = follow[index].Smoothing / 100f;
    27.             var target = follow[index].Target;
    28.  
    29.             var x = transform.position.x * (1 - scale) + position[target].Value.x * scale;
    30.             var y = transform.position.y * (1 - scale) + position[target].Value.y * scale;
    31.  
    32.             transform.position = new Vector3(x, y, transform.position.z);
    33.         }
    34.     }
    35.  
    36.     private ComponentGroup group;
    37.  
    38.     protected override void OnCreateManager(int capacity)
    39.     {
    40.         group = GetComponentGroup(ComponentType.ReadOnly<Follow>(), typeof(Transform));
    41.     }
    42.  
    43.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    44.     {
    45.         var transforms = group.GetTransformAccessArray();
    46.         var job = new Job(group, GetComponentDataFromEntity<Position2D>(true));
    47.         return job.Schedule(transforms, inputDeps);
    48.     }
    49. }
    And to set the entity from a game object I've got the following system.

    Code (CSharp):
    1. public struct CopyFollowTarget : IComponentData { }
    2.  
    3. public class CopyFollowTargetComponent : ComponentDataWrapper<CopyFollowTarget> { }
    4.  
    5. public class FollowTarget : MonoBehaviour
    6. {
    7.     public GameObject Target;
    8. }
    9.  
    10. public class CopyFollowTargetSystem : ComponentSystem
    11. {
    12.     public struct Data
    13.     {
    14.         public int Length;
    15.         public ComponentDataArray<CopyFollowTarget> Copy;
    16.         public ComponentDataArray<Follow> Follow;
    17.         public ComponentArray<FollowTarget> CopyData;
    18.         public EntityArray Entity;
    19.     }
    20.  
    21.     [Inject] private Data data;
    22.  
    23.     protected override void OnUpdate()
    24.     {
    25.         for (int i = 0; i < data.Length; i++)
    26.         {
    27.             var targetEntity = data.CopyData[i].Target.GetComponent<GameObjectEntity>().Entity;
    28.             data.Follow[i] = new Follow { Smoothing = data.Follow[i].Smoothing, Target = targetEntity };
    29.             PostUpdateCommands.RemoveComponent<CopyFollowTarget>(data.Entity[i]);
    30.         }
    31.     }
    32. }