Search Unity

Rewrite as a JobComponentSystem

Discussion in 'Scripting' started by DreamersINC, Oct 10, 2019.

  1. DreamersINC

    DreamersINC

    Joined:
    Mar 4, 2015
    Posts:
    131
    Question is possible to write the following code as JobComponentSystem using 2019.2.6 with entities .0.1.1 preview?
    The issue I am having is I have 2 entity in which I need to make changes to. My guard entity need to find a station the needs a guards and once it does it increase the guard count at that station so another guard doesnt get assigned there.

    upload_2019-10-10_6-54-18.png
     
  2. ProtagonistKun

    ProtagonistKun

    Joined:
    Nov 26, 2015
    Posts:
    352
    Consider making it easier for people to read your code by using code tags instead of a screenshot.
     
  3. DreamersINC

    DreamersINC

    Joined:
    Mar 4, 2015
    Posts:
    131
    Was rushing this morning to get something out before hitting the road. Wasnt thinking
    Code (CSharp):
    1. namespace IAUS.ECS.Systems
    2. {
    3.     public class GetGuardPoint : ComponentSystem
    4.     {
    5.         public EntityQueryDesc Guards= new EntityQueryDesc()
    6.         {
    7.             All = new ComponentType[] { typeof(Guard), typeof(LocalToWorld) }
    8.  
    9.         };
    10.         public EntityQueryDesc post = new EntityQueryDesc()
    11.         {
    12.             All = new ComponentType[] { typeof(GuardStationComponent), typeof(LocalToWorld) }
    13.  
    14.         };
    15.  
    16.         protected override void OnUpdate()
    17.         {
    18.             Entities.With(GetEntityQuery(Guards)).ForEach((Entity entity, ref Guard GC, ref LocalToWorld toWorld) => {
    19.                 if (!GC.Assigned())
    20.                 {
    21.                     float3 PostLocation = new Vector3();
    22.                     Entity ClosestPost = Entity.Null;
    23.                     float3 CurrentPosition = toWorld.Position;
    24.                     GuardStationComponent closest = new GuardStationComponent();
    25.                     Entities.With(GetEntityQuery(post)).ForEach((Entity entityPost, ref GuardStationComponent Station, ref LocalToWorld transform) => {
    26.                         if (Station.NumOfAssignedGuards >= Station.NumberOfGuardRequired)
    27.                         {
    28.                             return;
    29.                         }
    30.                         else
    31.                         {
    32.                             if (ClosestPost == Entity.Null)
    33.                             {
    34.                                 ClosestPost = entityPost;
    35.                                 PostLocation = transform.Position;
    36.                                 closest = Station;
    37.                             }
    38.                             else
    39.                             {
    40.                                 if (Vector3.Distance(CurrentPosition, transform.Position) < Vector3.Distance(CurrentPosition, PostLocation))
    41.                                 {
    42.                                     // this target is closer
    43.                                     ClosestPost = entityPost;
    44.                                     PostLocation = transform.Position;
    45.                                 }
    46.                             }
    47.                         }
    48.  
    49.                     });
    50.                     if (!PostLocation.Equals(new float3(0, 0, 0)))
    51.                     {
    52.                         GC.TargetLocation = PostLocation;
    53.                     }
    54.  
    55.                     Entities.With(GetEntityQuery(post)).ForEach((ref GuardStationComponent Station, ref LocalToWorld transform) => {
    56.                         if (PostLocation.Equals(transform.Position))
    57.                         {
    58.                             Station.NumOfAssignedGuards++;
    59.                         }
    60.  
    61.                     });
    62.  
    63.                 }
    64.             });
    65.  
    66.         }
    67.     }
    68. }
     
  4. ProtagonistKun

    ProtagonistKun

    Joined:
    Nov 26, 2015
    Posts:
    352
    If I understand correctly you are moving guards around but want to move them using the job system? The first thing would be to see if it works without using the job system.I assume you started from there. In any case, you can write anything in the job system if you want to, but the question would be if its necessary/better than doing it on the main. I have not worked with the Job system, but if its the same as async tasks in c# they cant interact with objects on the main thread...
     
  5. DreamersINC

    DreamersINC

    Joined:
    Mar 4, 2015
    Posts:
    131
    No, The code is for the guard entity to find a empty guard station and get assign the location. Once the station location is assigned, the stations count of assigned guards is increase. The issues is that doing so in a jobcomponentsystem only allows of one entity type to be used at a time. So I can assign a guard a station but I can not increase the station's count of assigned guards.
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Based on reading last response, I would consider following.

    Each guard is an entity.
    Each station is an entity.
    If station is empty, assign empty component tag, to allow gas system query search.
    Once guard found an empty station, remove empty component tag from station, now indicating that station is occupied by at least one guard.
    If you consider multiple guards per station, use dynamic buffer on stations, storing references to guard entities.
    Also, guard will need component with entity reference, to occupied station.

    Is these makes sense for your case? Is something would feel your requirement?
     
  7. DreamersINC

    DreamersINC

    Joined:
    Mar 4, 2015
    Posts:
    131
    I mean it works but that's a messy implementation. Stations don't need to have a reference to the guard entity. it just need to have a count of the number of guard assigned to it. Just need to increment the NumberOfAssigned variable in the station component once the system applies it
     
  8. DreamersINC

    DreamersINC

    Joined:
    Mar 4, 2015
    Posts:
    131
    Pulled my hair for a bit but unite Copenhagen talk had the solution


    Code (CSharp):
    1.     public class GetGuardPointJob : JobComponentSystem
    2.     {
    3.         public EntityQueryDesc posts = new EntityQueryDesc()
    4.         {
    5.             All = new ComponentType[] { typeof(GuardStationComponent), typeof(LocalToWorld) }
    6.  
    7.         };
    8.  
    9.         public struct Jobas : IJobForEachWithEntity<Guard>
    10.         {
    11.             [NativeDisableParallelForRestriction] public ComponentDataFromEntity<GuardStationComponent> CDFEGP;
    12.             [ReadOnly] [NativeDisableParallelForRestriction] public ComponentDataFromEntity<LocalToWorld> CDFETrans;
    13.  
    14.             [DeallocateOnJobCompletion] public NativeArray<Entity> posts;
    15.             public void Execute(Entity entity, int index, ref Guard GC)
    16.             {
    17.                 if (!GC.Assigned())
    18.                 {
    19.                     LocalToWorld toWorld = CDFETrans[entity];
    20.                     float3 PostLocation = new Vector3();
    21.                     Entity ClosestPost = Entity.Null;
    22.                     float3 CurrentPosition = toWorld.Position;
    23.                     GuardStationComponent closest = new GuardStationComponent();
    24.                     foreach (Entity entityPost in posts)
    25.                     {
    26.                         GuardStationComponent Station = CDFEGP[entityPost];
    27.                         LocalToWorld transform = CDFETrans[entityPost];
    28.                         if (Station.NumOfAssignedGuards >= Station.NumberOfGuardRequired)
    29.                         {
    30.                             return;
    31.                         }
    32.                         else
    33.                         {
    34.                             if (ClosestPost == Entity.Null)
    35.                             {
    36.                                 ClosestPost = entityPost;
    37.                                 PostLocation = transform.Position;
    38.                                 closest = Station;
    39.                             }
    40.                             else
    41.                             {
    42.                                 if (Vector3.Distance(CurrentPosition, transform.Position) < Vector3.Distance(CurrentPosition, PostLocation))
    43.                                 {
    44.                                     // this target is closer
    45.                                     ClosestPost = entityPost;
    46.                                     PostLocation = transform.Position;
    47.                                 }
    48.                             }
    49.                         }
    50.  
    51.                     };
    52.                     if (!PostLocation.Equals(new float3(0, 0, 0)))
    53.                     {
    54.                         GC.TargetLocation = PostLocation;
    55.                         GuardStationComponent test = CDFEGP[ClosestPost];
    56.                         test.NumOfAssignedGuards++;
    57.  
    58.                         CDFEGP[ClosestPost] = test;
    59.                     }
    60.                 }
    61.             }
    62.  
    63.         }
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Sure if that what you need, that even better.
    What matter is, you figured out your own solution.

    Code (CSharp):
    1. if (Vector3.Distance(CurrentPosition, transform.Position) < Vector3.Distance(CurrentPosition, PostLocation))
    You should be using floats really. float3 specifically.
    Also, you can subtract both float3 (Vectors3) before calculating distance. For even reducing further computation overhead, you could use 'squared' distance (before get squared).

    Also, you should be able to add burst to the job.