Search Unity

Execution order of Systems

Discussion in 'Entity Component System' started by BanJaxe, Mar 20, 2018.

  1. BanJaxe

    BanJaxe

    Joined:
    Nov 20, 2017
    Posts:
    47
    Other ECS implementations I have used typically execute systems in the order they are registered with the world context. How do I do that in Unity?

    In these github docs there is a section on World creation but unfortunately the two links are currently broken.
     
  2. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,643
    I am not familiar with the Unity implementation, but in general relying on order of execution of the systems is not a good practice. It's a weakness that can be easily broken by coders that are not aware of the order of sequence constraint. I know these problems may not be seen as a problem when you work on your own, but Unity wants to move to triple A production where these are real issues.
     
  3. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    I downloaded the beta...it still lacks some basic documentation or I did not find it.

    I did not find a documentation for Unity.Entities but browsing through the namespace suggests there are attributes for that allow some control over execution order, i.e. Unity.Entities.UpdateAfterAttribute -> looks like an attribute you can set to delay execution until some other systems are done...

    I am fairly new to ECS and I think I will give it a few weeks and wait for more info to become available...
     
    Egad_McDad, lianaqiang and sebas77 like this.
  4. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    On the github page you linked it is briefly mentioned that ordering is done automatically. But I'm not sure if that relates to execution order.
     
  5. BanJaxe

    BanJaxe

    Joined:
    Nov 20, 2017
    Posts:
    47
    Hey thanks for the replies, I did get the attributes working:

    Code (csharp):
    1.  
    2. using Unity.Entities;
    3. using UnityEngine;
    4.  
    5. public class TestASystem : ComponentSystem
    6. {  
    7.     protected override void OnUpdate()
    8.     {
    9.         Debug.Log("TestASystem on frame " + Time.frameCount);
    10.     }
    11. }
    12.  
    13. [UpdateAfter(typeof(TestASystem))]
    14. public class TestBSystem : ComponentSystem
    15. {
    16.     protected override void OnUpdate()
    17.     {
    18.         Debug.Log("TestBSystem on frame " + Time.frameCount);
    19.     }
    20. }
    21.  
    22. [UpdateAfter(typeof(TestBSystem))]
    23. public class TestCSystem : ComponentSystem
    24. {
    25.     protected override void OnUpdate()
    26.     {
    27.         Debug.Log("TestCSystem on frame " + Time.frameCount);
    28.     }
    29. }
    30.  


    I'm not sure this is the "correct" way to do it but it seems to work for any order. UpdateBefore also works.

    I found UpdateInGroup but not sure how to use it yet.
     
    Last edited: Mar 21, 2018
    JorMed and sebas77 like this.
  6. kmuzykov

    kmuzykov

    Joined:
    Jul 1, 2013
    Posts:
    1
    I am relatively new to Entity Component Systems, but I feel that having an option to order systems is needed if you care about things happening same frame.

    For example you might have DamageSystem and DeathSystem. If the order is DamageSystem and then DeathSystem then entities will die same frame their HP goes to 0, if the order is DeathSystem and then DamageSystem then entities will die next frame. That might be important.

    I agree that not relying on the order of the systems is perfect, but I had few examples when I actually couldn't achieve that. However, I don't exclude the probability that I might be doing something wrong.

    Having UpdateAfter attribute works, but I would prefer to have the order of systems configured in one place rather than scattered around all systems.

    Also it might be useful to be able to have different set of systems per World. Can you do that now?

    I would say having entityManager.RegisterSystem to register systems explicitly and in particular order would allow both. And if you don't care about the order it is as easy as just adding 1 line per system. I don't think it is such a big overhead. Also it lowers the chances of you forgetting about the system laying around in some folder and doing something, but being added automagically to your world.
     
  7. RootCauseProductions

    RootCauseProductions

    Joined:
    Feb 1, 2018
    Posts:
    31
    I am assuming (ya, I know) that you are using a single component that is common between the two systems. I'll call it HealthData . Looking at the TwoStick example, there are several systems that annotate ComponentDataArrays with [ReadOnly]. The documentation does this as well, but it never points this out in the text. What I think is happening (don't have access to the code and can't find anything in the docs) is the scheduler uses that annotation to determine what is being updated and what is not. From there, it can schedule the updates before the reads.

    In your example, you would annotate HealthData in the DeathSystem like this
    Code (csharp):
    1.  [ReadOnly] public ComponentDataArray<HealthData> Health;
    The documentation makes reference to being able to do that, but the links are dead and there is a note that indicates it is not working yet.
     
  8. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Tony_Max likes this.
  9. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    I don't quite know if I understand that page. When you're specifying UpdateBefore and UpdateAfter for an update group, do you put the attribute on the group markers or the component systems?

    Ie. is it this:

    Code (csharp):
    1. public class UpdateGroup1 {}
    2. public class UpdateGroup2 {}
    3.  
    4. [UpdateBefore(typeof(UpdateGroup2))]
    5. [UpdateInGroup(typeof(UpdateGroup1))]
    6. class MySystemA : ComponentSystem
    7.  
    8. [UpdateInGroup(typeof(UpdateGroup1))]
    9. class MySystemB : ComponentSystem
    10.  
    11. [UpdateInGroup(typeof(UpdateGroup2))]
    12. class MySystemC : ComponentSystem
    13.  
    14. [UpdateInGroup(typeof(UpdateGroup2))]
    15. class MySystemD : ComponentSystem
    Or is it:

    Code (csharp):
    1. [UpdateBefore(typeof(UpdateGroup2))]
    2. public class UpdateGroup1 {}
    3. public class UpdateGroup2 {}
    4.  
    5. [UpdateInGroup(typeof(UpdateGroup1))]
    6. class MySystemA : ComponentSystem
    7.  
    8. [UpdateInGroup(typeof(UpdateGroup1))]
    9. class MySystemB : ComponentSystem
    10.  
    11. [UpdateInGroup(typeof(UpdateGroup2))]
    12. class MySystemC : ComponentSystem
    13.  
    14. [UpdateInGroup(typeof(UpdateGroup2))]
    15. class MySystemD : ComponentSystem
     
  10. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Both are correct, it depends on what you want to do. In the former case MySystemA will update before everything in Group2, but there is no guarantee MySystemB will update before the group. In the latter case everything in Group1 will update before everything in Group2.
    Specifying a requirement on a group will right now apply that requirement to everything in the group. I will try to make it more clear in the docs next week.
     
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Okay, that makes sense! It's also really flexible, I can have a single file that contains all the groups and their update orders, and then fine-tune on a per-system basis.

    I assume there's some kind of infinite loop checking implemented?
     
  12. dreamerflyer

    dreamerflyer

    Joined:
    Jun 11, 2011
    Posts:
    927
    ComponentSystem and JobComponentSystem both can run Like Monobehavior and no need drag to gameobject?
     
  13. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Yes, there are checks for loops in dependencies. If one is detected it will ignore one of the constraints and print an error in the console / log file.
     
  14. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Correct, there is no need to use any GameObject when using ComponentSystem / JobComponentSystem. Their OnUpdate method will be called without any MonoBehaviours.
     
  15. dreamerflyer

    dreamerflyer

    Joined:
    Jun 11, 2011
    Posts:
    927
    but,how to control them run and stop?when I need ,to start to run OnUpdate()
     
  16. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    For what purpose would you need that? (Maybe I misunderstood your question)

    If you no longer want to update an entity from a particular system, remove one of the "filter components" (for that system) of that entity.

    E.g. remove just one of the following Component (CompA, CompB, CompC) of the entity. The System wont handle that entity anymore.
    A component can even be an empty struct without data. Just us such component as tags. But use it as SharedComponent if possible...

    (It could be that my code isn't spelled correctly...)
    Code (CSharp):
    1.  
    2. // Handle entities with CompA, CompB and CompC attached to it
    3. class MySystem : ComponentSystem {
    4.      struct Data {
    5.             CompA compA;
    6.             CompB compB;
    7.             CompC compC;
    8.      }
    9.  
    10.      public override void OnUpdate() {
    11.           foreach(var entity in GetEntities<Data>()) {
    12.                ....
    13.           }
    14.      }
    15. }
    16.  
    17. // System to remove CompC form entities with CompA, CompB and CompC attached to it
    18. class MySystemRemover : ComponentSystem {
    19.      struct Data {
    20.             public EntityArray Entities;
    21.             public int Length;
    22.             [ReadOnly] public ComponentArray<CompA> compA;
    23.             [ReadOnly] public ComponentArray<CompB> compB;
    24.             public ComponentArray<CompC> compC;
    25.      }
    26.     [Inject] Data m_Data;
    27.  
    28.      public override void OnUpdate() {
    29.           for(int i=0; i<m_Data.Length; i++) {
    30.                BufferedCommand.RemoveComponent<CompC>(m_Data.Entities[i]);
    31.           }
    32.      }
    33. }
    34.  
     
    Last edited: Mar 26, 2018
    illinar likes this.
  17. dreamerflyer

    dreamerflyer

    Joined:
    Jun 11, 2011
    Posts:
    927
    I mean ,whether componentSystem has enable and disable property to set run and stop.And,like ,componentSystemA and componentSystemB,how to control which system's Onupdate excuse first,and how can i find the running codes in current scene?
     
    Last edited: Mar 26, 2018
  18. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Windows -> Entity Debugger

    There you can turn on and of systems. (This can also be archived by code using ComponentSystem.Enabled.)
    You also see entities realated to that systems and there props. Execution order...


    This can be specifiet by UpdateBefore/ UpdateAfter attribute

    Code (CSharp):
    1. public class MySystemA : ComponentSystem {
    2.    ....
    3. }
    4.  
    5. [UpdateAfter(typeof(MySystemA))]
    6. public class MySystemB : ComponentSystem {
    7.    ....
    8. }
    9.    
    In the code above: MySystemA will be executed bevor MySystemB.
    If you dont define such execution order.



    For more info take a look of my posts here.
     
    Last edited: Mar 26, 2018
    dreamerflyer likes this.
  19. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    @dreamerflyer Also if you want to disable for example a gravity system (bad example) temporarily instead of removing GravityUser component from all entities that have it, you can create an entity with a DisableGravity component and inject that separately or have it as a shared component. And when that component is present in the game or has value = true you just quit (return;) on the system update.
     
  20. FROS7

    FROS7

    Joined:
    Apr 8, 2015
    Posts:
    26
    This is a stupid question, as i am new to this and dont know what im doing.

    Why do you use a foreach loop in MySystem but injection and a regular for loop in MySystemRemover?
     
  21. floboc

    floboc

    Joined:
    Oct 31, 2017
    Posts:
    91
    I don't know if this is an intended behaviour or not but it seems that UpdateBefore/UpdateAfter rely on some declaration order of the groups.

    For instance this code generates a null exception :

    Code (CSharp):
    1. [UpdateBefore(typeof(UpdateGroupInput))]
    2. public class UpdateGroupInitialization
    3. {
    4. }
    5.  
    6. [UpdateBefore(typeof(UpdateGroupGameLogic))]
    7. public class UpdateGroupInput
    8. {
    9. }
    10.  
    11. [UpdateBefore(typeof(UpdateGroupCollisions))]
    12. public class UpdateGroupGameLogic
    13. {
    14. }
    15.  
    16. [UpdateBefore(typeof(UpdateGroupRender))]
    17. public class UpdateGroupCollisions
    18. {
    19. }
    20.  
    21. public class UpdateGroupRender
    22. {
    23. }

    While this code does not :

    Code (CSharp):
    1. public class UpdateGroupInitialization
    2. {
    3. }
    4.  
    5. [UpdateAfter(typeof(UpdateGroupInitialization))]
    6. public class UpdateGroupInput
    7. {
    8. }
    9.  
    10. [UpdateAfter(typeof(UpdateGroupInput))]
    11. public class UpdateGroupGameLogic
    12. {
    13. }
    14.  
    15. [UpdateAfter(typeof(UpdateGroupGameLogic))]
    16. public class UpdateGroupCollisions
    17. {
    18. }
    19.  
    20. [UpdateAfter(typeof(UpdateGroupCollisions))]
    21. public class UpdateGroupRender
    22. {
    23. }

    However they define the same order (there are no other groups involved in my projects).
    The exception I get is :

    "NullReferenceException: Object reference not set to an instance of an object
    Unity.Entities.ScriptBehaviourUpdateOrder+ScriptBehaviourGroup..ctor (System.Type grpType, System.Collections.Generic.IDictionary`2[TKey,TValue] allGroups, System.Collections.Generic.HashSet`1[T] circularCheck)"


    Do you have any info about that ?

    Thanks !
     
  22. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    i ran into the same issue when i tested this a while back. If I recall correctly, it requires that the classes are sequentially written in an order that makes them "known" to the previous groups - looks like a beta issue / bug.

    it might work if you just change the order the classes are written in your first example (i.e. reverse) --- i forgot if this solved the issue or not.
     
  23. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    thanks for reporting the issue. We will look at it and see if we can change the logic to allow classes to be in any order.
     
  24. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Currently, setting order of systems with attributes does not scale really well and make it quite hard to figure out the order of Systems. Even at later time we have the Entity Debugger that will able to visualize the order of systems u still need to switch Unity and IDE back and forth to debug and configure to get the right order.

    After I tried ECS for some time, I suggest the best approach to group systems and setup order of systems is to make it able to configutre at Entity Debugger directly. The way to change the order of system can design it like Reorderable List Editor API that u can drag up and down to change the order. As there are auto dependency management to setup the order, I think make the configuration at Editor will have the direct feedback to know which system can change order and which system not able to change order because of its dependencies.
     
    Spy-Shifty likes this.
  25. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    I also like this approach.
    This will require that the entity debugger shows all systems in editmode as well. So that we can change the order of systems and the grouping without running unity in playmode. It would be usefull if we can both, changing order in edit- and in playmode

    Maybe the grouping can be done like in the Timeline
     
    optimise likes this.
  26. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    @optimise - for the time being, I found the best approach to be:
    1. Setup "Update Groups"
    2. Define order of "update groups"
    3. Assign your systems to the "update groups" [UpdateInGroup]
    4. Within "update groups" you can still define order (but for clarity I would rather not and keep the groups at a level where order of systems within a group does not matter)
     
  27. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    The ordering system is implemented on top of the custom managed player API (https://docs.unity3d.com/2018.1/Doc...e/Experimental.LowLevel.PlayerLoopSystem.html), which means that it is possible for us to expose a data driven approach.

    We will likely provide something like this, it makes total sense in my opinion, but at the moment we are focusing on other lower level concepts.

    One of the questions is how to make sure that a data-driven/visual approach can cope well with having some of the ordering defined in code.
     
  28. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    I think make it only can choose one way to do it instead of supporting both ways together. So, there will be an option at Entity Debugger to choose whether using data-driven/visual approach or code. If using code, it will disable the ability to configure at Entity Debugger. And if using data-driven/visual approach it will throw compile error when writing ordering defined in code. If going code generation route (see below) then it will just overwrite user defined code and make problem solving even easier. So, there will be become only one center place to setup order of systems.

    Another thing I think you guys should look into is code generation. Maybe data-driven/visual approach to do this systems order will not have huge performance penalty and easy to use issue. But I think for Animator Component, I would like to see something in the future that we no longer need to Animator.StringToHash() anymore. When we configure something at Animator Editor, u will generate the code in the background for u instantly. For example, when u set Speed parameter, it will generate a Const Int Speed parameter code for you and u can use it directly at IDE. In future I think Animator will become as a package in Package Manager and the generated code will generate at there to make sure main Project Asset folder cleaner.

    For incremental compiler, I would like to see that it will no longer freeze the Unity when compiling code so I and keep continue do my work at Unity Editor.
     
    Last edited: Apr 12, 2018
  29. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    My Approach would be:
    You still should have the possibillity to change the order of your systems in the editor.
    But you shouldn't be able to break your code constrains (ExecuteAfter, ExecuteBefor).

    If you have an execution order defined by code, lets say
    SystemB should run after SystemA

    Than it shouldn't be possible to drag SystemB befor SystemA and visa vie in the entity editor.
    OR
    update the order automatically, so that if you drag SystemA after SystemB thanSystemB will be moved after SystemA again.

    In my mind, ExecuteAfter and ExecuteBefor,... are constraints. (As it is right now)
    It's not saying run SystemB right after SystemA. It's only says: well SystemB should be run after SystemA, but other Systems can also run befor SystemB and after SystemA as well. So that you can have a constallation like this:

    SystemA
    SystemC
    SystemD
    SystemE
    SystemB


    If this approach isn't clear to you, let me know!
     
    deus0 likes this.
  30. scvnathan

    scvnathan

    Joined:
    Apr 29, 2016
    Posts:
    75
    By the way, how experimental is the exposed PlayerLoopSystem API right now? Can we count on it being stable for production use soon (this year)? Or are there still API/behavioral changes coming?
     
  31. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    The problem with this approach is that it might collide with using packages that were designed to rely on one method or the other. You get two packages configured to work in two different ways, and you get errors.
    I think we should probably understand which system should have priority over the other.

    Codegen is a double edge sword, mostly for discoverability. But I agree with you that it is something quite important to figure out. The incremental compiler framework allows us to generate/modify code behind the scenes and on the fly while compiling, so we might find a way to make codegen less problematic and start using it.

    It is a background service, so it is not the compilation causing freezes (I think). The freezing happens when we reload domains, and there is not much we can do to prevent that, other than making everything way more efficient or figuring out a way to avoid reloading.
     
  32. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    yeah, I think that constraining the UI this way is worth a try. And, given that everything is open and in C#, it is also possible for you guys to give it a shot in case you are impatient :)

    (I'm not saying we won't figure out improvements, but it is still a good option now that source is available ...)
     
    deus0, optimise and Spy-Shifty like this.
  33. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    It is stable, but we might refining it a little bit. It will definitely go out of experimental in either .2 or .3; we didn't find any major issues yet, and the API has been heavily used by a lot of our public and internal demos, and by many customer projects.
     
  34. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    ETA for next version update? Until now it's still Entities 0.0.11. lol
     
  35. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Reloading domains has gotten way slower in recent versions - it takes a bunch longer than compiling. I suspect it's due to assembly definitions (we use a bunch), but I can't tell for sure - editor profiling seems to not record anything during domain reloads.
     
  36. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    We are planning to increase the release frequency, but we need to wait for 2018.1 RC first (so that the package can work with the regular Unity build) and also improving the internal CI and publishing system.
     
    optimise likes this.
  37. GabrieleUnity

    GabrieleUnity

    Unity Technologies

    Joined:
    Sep 4, 2012
    Posts:
    116
    AssemblyDefinitions are well covered by performance tests, and they shouldn't be the problem. We had one or two performance-related regressions that we fixed. What usually happens, is that the reload is impacted by some user code that the users don't even notice it is running. Among the other things, we want to improve the profiler to provide detailed information about what happens when you enter play mode or reload domains so that problems can be caught more precisely.
     
  38. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Does Unity and IDE communicate each other with REST feature still ongoing? I think with this feature u can tell Unity to compile instantly when saving script at IDE. So, you dun need to go back to Unity to compile script and it will solve freeze issue in this way until figuring out better solution.
     
  39. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    That happens in the latest (early access) version of Rider. So saving in Rider triggers a compile in Unity without having to tab over to Unity.
     
    optimise likes this.
  40. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    451
    I have a problem with execution order.
    Change frame system is not executed as if ContdownEndedSystem have been executed before ChangeFrameSystem despite the attribute.
    Code (CSharp):
    1. public class CountdownEndedSystem : ComponentSystem
    2.     {
    3.         public struct Data
    4.         {
    5.             public int Length;
    6.             public EntityArray EntityID;
    7.             public ComponentDataArray<CountdownEnded> CountDownEnded;
    8.         }
    9.  
    10.         [Inject] private Data m_Data;
    11.  
    12.         protected override void OnUpdate()
    13.         {
    14.             UnityEngine.Debug.Log(this.GetType());
    15.             for (int i = 0; i < m_Data.Length; i++)
    16.             {
    17.                 var entity = m_Data.EntityID[i];
    18.                 if (EntityManager.Exists(entity))
    19.                     PostUpdateCommands.RemoveComponent<CountdownEnded>(entity);
    20.             }
    21.         }
    22.     }

    Code (CSharp):
    1. [UpdateBefore(typeof(CountdownEndedSystem))]
    2.     public class ChangeFrameSystem : ComponentSystem
    3.     {
    4.         public struct Data
    5.         {
    6.             public int Length;
    7.             public EntityArray EntityID;
    8.             public ComponentDataArray<TimePerFrame> TimePerFrame;
    9.             public ComponentDataArray<Frames> Frames;
    10.             public ComponentDataArray<Frame> Frame;
    11.             public ComponentDataArray<CountdownTimer> CountDown;
    12.             public ComponentDataArray<CountdownEnded> CountDownEnded;
    13.         }
    14.  
    15.         [Inject] private Data m_Data;
    16.  
    17.         protected override void OnUpdate()
    18.         {
    19.             UnityEngine.Debug.Log(this.GetType());
    20.             for (int i = 0; i < m_Data.Length; i++)
    21.             {
    22.                 var entity = m_Data.EntityID[i];
    23.                 var time = m_Data.TimePerFrame[i].Value + m_Data.CountDown[i].Time;
    24.                 byte frame = (byte)(m_Data.Frame[i].Current + 1);
    25.                 if (frame == m_Data.Frames[i].Count)
    26.                     frame = 0;
    27.  
    28.                 PostUpdateCommands.SetComponent<CountdownTimer>(entity, new CountdownTimer() { Time = time });
    29.                 PostUpdateCommands.SetComponent<Frame>(entity, new Frame() { Current = (byte)frame });
    30.             }
    31.         }
    32.     }
     
  41. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Use the Entity Debugger window and find out if you really have any entity with all 5 kinds of component attached?
     
  42. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    451
    Yes, I have when I disable system that removes CountdownEnded component than it works properly.
     
  43. floboc

    floboc

    Joined:
    Oct 31, 2017
    Posts:
    91
    Just found a new bug regarding update order.

    If you define some groups and order group, the execution order is totally broken if a group is empty (i.e. if there is no system belonging to a group).

    For instance let's say you define this order:

    Code (CSharp):
    1.  
    2. public class UpdateGroupA
    3. {
    4. }
    5.  
    6. [UpdateAfter(typeof(UpdateGroupA))]
    7. public class UpdateGroupB
    8. {
    9. }
    10.  
    11. [UpdateAfter(typeof(UpdateGroupB))]
    12. public class UpdateGroupC
    13. {
    14. }
    Normally all systems belonging to group A should execute before those in C.
    However if no system belong to group B, I observed that some systems in A were actually updated after some in C in the same frame, which should not happen.
     
  44. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    It would be really nice if UpdateBefore/UpdateAfter could recognize our own custom PlayerLoopSystem's.

    I'm able to get around it now by taking the player loop system ECS generates and reordering/merging in my loops. But it seems PlayerLoopSystem itself should have a higher level abstraction to coordinate merging of custom loops from different parts of the code.

    Right now more then one party creating a custom loop and S*** is likely to break. Plus, if you don't handle the merging before anything starts running, then some systems can't be aware. Like ECS has no way to know about my custom loops because they necessarily get set after ECS does it's customizations.
     
  45. mmankt

    mmankt

    Joined:
    Apr 29, 2015
    Posts:
    49
  46. pavelzinov42

    pavelzinov42

    Joined:
    Feb 10, 2017
    Posts:
    3
    This is only nice on paper, just like OOP.
    In reality you have to know the flow of your code.
    Especially in the ECS where systems code is not usually that large but in order for your whole feature to work you have to execute several systems in specific order. This is especially essential in the networking code since the whole attitude of "I don't care when this is going to be executed" results in significant latency for your end user.
     
  47. sinaari

    sinaari

    Joined:
    Jan 28, 2019
    Posts:
    47
    Wait. If I understand correctly, is this thread saying that instead of having a neat list defined in one place in some configuration preset, where all systems are simply added in the required order to that list and can easily be seen and managed, the actual way is to have annotations scattered across multiple classes and files, coupling them and making it impossible to grasp the whole picture at a glance in code without looking at some special editor window that only shows the order when the application is running?
     
    sebas77 likes this.
  48. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Ya this has come up before. They have cleaned up a lot of the ordering/group logic recently. Source ordering/group data is abstracted out more but not completely. They could be moving to abstracting that out completely so you can plug in whatever you want. Hard to say.
     
  49. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    I believe one of the reasons for the current approach is to support future asset packages that include systems.

    the data defining when a system is run can be contained entirely in the system definition.

    I’m not voicing an opinion about this approach.
     
  50. c0ffeeartc

    c0ffeeartc

    Joined:
    Jul 23, 2015
    Posts:
    42
    Here is a hack for custom systems order.
    But likely this hack will not work soon.

    Code (CSharp):
    1. [Obsolete("Use SortSystems(). (RemovedAfter 2020-07-30)")]
    2. public virtual void SortSystemUpdateList()
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Entities;
    3.  
    4. [UpdateInGroup(typeof(SimulationSystemGroup))]
    5. public class CustomSystems : ComponentSystemGroup
    6. {
    7.     public override void SortSystemUpdateList( )
    8.     {
    9.         var backup = new List<ComponentSystemBase>();
    10.         backup.AddRange( m_systemsToUpdate );
    11.         base.SortSystemUpdateList(  );
    12.         m_systemsToUpdate.Clear(  );
    13.         m_systemsToUpdate.AddRange( backup );
    14.     }
    15. }
    Code (CSharp):
    1. var world = World.DefaultGameObjectInjectionWorld;
    2. var systems = world.GetOrCreateSystem<CustomSystems>(  );
    3.  
    4. systems.AddSystemToUpdateList( world.GetOrCreateSystem<System1>(  ) );
    5. systems.AddSystemToUpdateList( world.GetOrCreateSystem<System2>(  ) );
    6. systems.AddSystemToUpdateList( world.GetOrCreateSystem<System3>(  ) );
    7.