Search Unity

Time Interval ComponentSystem And JobComponentSystem

Discussion in 'Entity Component System' started by herkip, Apr 18, 2019.

  1. herkip

    herkip

    Joined:
    Dec 21, 2013
    Posts:
    30
    Hi

    I figured how to use Time Interval on the component system but how would you guys approach the job component system with a similar outcome?


    Code (CSharp):
    1. public class TimeSystem : ComponentSystem
    2. {
    3.     private float _period = 0f;
    4.     private int _gameSpeed = 1;
    5.  
    6.     protected override void OnUpdate()
    7.     {
    8.         var deltaTime = Time.deltaTime;
    9.  
    10.         if (_period > _gameSpeed)
    11.         {
    12.             Entities.ForEach((ref GameTimer gameTimer) => Calculate(ref gameTimer));
    13.  
    14.             _period = 0;
    15.         }
    16.  
    17.         _period += deltaTime;
    18.     }
    19. }
    Thank you
     
  2. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    Denormalize it I think. Whenever I need a data that is really a "singleton" data (time is a good example here) I just create a component (WorldTime for example) and add it to ever entity that needs it. Then I create a system that runs in Initialization Group and writes to every WorldTime component. This way you can just process the data with IJobForEach and not worry about getting this data from some singular source in every system needing it.
    Writing:
    Code (CSharp):
    1.     [UpdateInGroup(typeof(InitializationSystemGroup))]
    2.     public class WorldTimeSystem : JobComponentSystem
    3.     {
    4.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    5.         {
    6.             return new WriteWorldTimeJob
    7.             {
    8.                 Time      = UnityEngine.Time.time,
    9.                 DeltaTime = UnityEngine.Time.deltaTime
    10.             }.Schedule(this, inputDeps);
    11.         }
    12.  
    13.         private struct WriteWorldTimeJob : IJobForEach<WorldTime>
    14.         {
    15.             [ReadOnly] public float Time;
    16.             [ReadOnly] public float DeltaTime;
    17.  
    18.             public void Execute([WriteOnly] ref WorldTime data)
    19.             {
    20.                 data.Time      = Time;
    21.                 data.DeltaTime = DeltaTime;
    22.             }
    23.         }
    24.     }
    25.  
    Processing:
    Code (CSharp):
    1.     public class StraightMovementSystem : JobComponentSystem
    2.     {
    3.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    4.         {
    5.             return new StraightMovementJob().Schedule(this, inputDeps);
    6.         }
    7.  
    8.         private struct
    9.             StraightMovementJob : IJobForEach<StraightMovement, WorldTime, Translation>
    10.         {
    11.             public void Execute([ReadOnly] ref  StraightMovement movement,
    12.                                 [ReadOnly] ref  WorldTime        worldTime,
    13.                                 [WriteOnly] ref Translation      position)
    14.             {
    15.                 position.Value = movement.StartPosition + movement.Velocity * (worldTime.Time - movement.StartTime);
    16.             }
    17.         }
    18.     }
    19.  
     
    herkip likes this.
  3. herkip

    herkip

    Joined:
    Dec 21, 2013
    Posts:
    30
    That will work for time yes. And thanks for your examples.

    In this case, though I mean how can I run the system every x seconds. I can add if statement inside IJobChunk but I still move data around because of that. The best option would be if I can not run Job at all if let's say 5 seconds as not been passed.
     
  4. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    I wouldn't worry about "moving the data around" too much. Just remember that reading the memory is what is costly, writing is nearly free :) Here is an example of BurstCompile job writing to 10000 entities:
    upload_2019-4-18_11-56-48.png

    It will utilize all the cores available and takes 0.02s anyway so CPU cost is negligible.

    About not running the job entirely I think you can do filtering based on ShaderComponent value but I never used it with Jobs so maybe someone more knowledgeable could point you in the right direction
     
  5. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    Hmm, I just checked and it seems that you can use IJobForEach with EntityQuery where you can use SetFilter to execute jobs only on the entites with given SharedComponent value
     
    Last edited: Apr 18, 2019