Search Unity

Why is Simulation the default system group?

Discussion in 'Entity Component System' started by Liburia, Mar 4, 2019.

  1. Liburia

    Liburia

    Joined:
    Jun 24, 2013
    Posts:
    10
    In regular Unity you use Update for the game logic while FixedUpdate is recommended for physics-related things. Is this different in ECS? Why?
     
  2. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    I'm guessing the ECS team feels that (at least for now) most ECS systems will involve pure calculations rather than rendering stuff. And in general, we should use fixed timestamp for pure calc and use Update for input and rendering-related stuff. Again just a guess.
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    ECS has no physics API yet.

    ECS is pretty good at rendering stuff. Specially thousands of objects. That significant advantage over Classic OOP.
     
  4. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    I wasn't saying ECS is good or bad at rendering, just that the amount of math code may be prioritized over rendering code. Hence the preference of SimulationSystemGroup as the default over PresentationSystemGroup.
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    That is not necessary true. At least not for every case.
    Yes you can use ECS, for math heavy applications, which is fine and you will be right.
    But you can use ECS as well, just to render 100s Thousands of entities, with little to none math. Something which isn't feasible in Classic OOP otherwise.
    That is why I said
     
  6. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    I think by using opinionated naming like that it encourage you to think about simulation and rendering separately rather than simulation THEN render. Previously I don't want to touch fixed update since it was known for physics stuff. Now I am tempted to calculate in that phase since putting everything in presentation now sounds wrong.
     
    JesOb, NotaNaN and Singtaa like this.
  7. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    Hello, I'm the engineer who worked on this change; hopefully I can shed some light on it. The decision to move "simulation" systems to the FixedUpdate phase was motivated by the DOTS principle of "determinism by default". In the DOTS world, iterative simulation work should be repeatable given identical inputs, which in turn requires a fixed timestep. The most straightforward way to arrange for this in Unity was to add the SimulationSystemGroup to the FixedUpdate phase.

    The intention is for this to be Unity's default behavior, not a hard requirement. We ultimately want the application to be in control of the update loop. An application that's willing to give up determinism should be able to opt out of a fixed timestep and return to a more familiar game loop, such as one with a variable timestep and one simulation tick per render tick.

    However, that opt-out mechanism doesn't exist yet in DOTS. We also don't have a solid solution in place to interpolate between the results of two consecutive simulation ticks, which would be necessary to fully decouple the presentation rate from the simulation rate. Meanwhile. there are legitimate pitfalls when running simulation code with a fixed timestep (and in FixedUpdate specifically). The duration of any frame rate spikes will be amplified, as the spike itself is followed by 1+ frames where the simulation step runs repeatedly to "catch up", which may in turn cause further hitches. Input processing is also more complicated, as it requires extra tracking to figure out which simulation tick a particular input event should apply to. For all these reasons, we'll be moving the system groups around the player loop in the next release:
    • SimulationSystemGroup will move from the end of FixedUpdate to the end of Update. The simulation tick rate will match the rendering tick rate, and both will be variable. This is a temporary workaround; long-term, we plan to move simulation back to a fixed timestep once we have more infrastructure in place to allow users to customize the structure of the game loop.
    • PresentationSystemGroup will move from the end of Update to the end of PreLateUpdate. Most notably, it will run after ScriptRunBehaviourLateUpdate and the Unity Animation update, and can react to changes made by those phases (e.g. the final animated transforms can be used to spawn VFX, track cameras to moving objects, etc.) while still running early enough to affect that frame's rendered output.
    Apologies for the churn; this remains an iterative process, and your feedback on the preview packages is invaluable in informing our design process.

    Related: If this sort of thing interests you, I highly recommend checking out Tyler Glaiel's recent article, which discusses the pros & cons of various game loop structures in much more detail.
     
    Last edited: Mar 6, 2019
  8. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    982
    I didn't understand the context of this. I just realized it now that I'm upgrading.
     
  9. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Thanks for the detailed explanation, I really like the direction in which this is going. I'd like to say 3 things:
    1. I don't feel like we'd need an automagical solution for interpolating things in the presentation world between simulation world updates (not sure if this is what you were suggesting). This sort of thing is arguably better done manually by users (aside maybe from default components that would provide basic transform interpolation for users who want it), and besides we already need to deal with this kind of stuff with rigidbodies and interpolation in legacy Unity
    2. In my experiments with making an ECS Physics engine and an ECS Online game framework, I've very often found the need to be able to easily call MyUpdateGroup.Update() manually. I think this would be a good feature to have built-into the ECS. Right now it's possible to store systems in a list somewhere and iterate on it and call Update() for each, but having a function that Updates all in a specific group would be much better from a UX perspective. It would save programmers from having to manually register systems in lists instead of simuply using the [UpdateInGroup] method. This sort of thing is pertinent for when we need to call a bunch of systems potentially multiple times per frame.
    3. Another issue I've run into is that there are times where you want multiple different FixedUpdates running simultaneously but at different timesteps. It would help a lot if users had the possibility to declare multiple FixedUpdates easily in the PlayerLoop, and then subscribe their systems to those new FixedUpdates. For example in an online game, you may want non-networked physics rigidbodies to be simulated at 50fps like they are by default in Unity, but you'd also want a different FixedUpdate running at 30fps that simulates your networked gameplay code (aka the "tickrate"). In this case, the non-networked rigidbodies would be purely aesthetic and would not affect player movement/projectiles/etc... Player ragdolls in Halo Reach are an example of this.

    These are just a few things that I feel would make the ECS more useable in a wider range of scenarios
     
    Last edited: Mar 7, 2019
    JesOb, recursive and NotaNaN like this.
  10. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    I'll have to get back to you on your other points, but I can address the second one immediately:
    This should already be supported. Since a ComponentSystemGroup is derived from ComponentSystemBase, it has an Update() method like any other system. If you'd like more control over exactly when it's ticked, you can mark the group as [DisableAutoCreation] (to prevent it from participating in default World initialization), create it manually with var group = World.GetOrCreateManager<MyUpdateGroup>(), and then update all systems in that group with group.Update() from your own (main-thread) code. It's not quite as smooth as it could be yet, and we intend to improve the custom bootstrap feature to support use cases like this, but the basic functionality should be there today.
     
    elZach, JesOb, Seb-1814 and 3 others like this.
  11. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Thanks for the insights. Splitting logic from interpolated rendering was something I used to do from 20 years ago up until Unity came around so it's not a new concept, but I really appreciate splitting logic (simulation) from rendering.

    Keeping things in sync however for rendering and logic is tricky with things like the the animator, because often animation will be used to position a collider (on a sword for example), so we would probably want to animate things in sim as well, before somehow interpolating it, or doing the work sort of twice...
     
    AcidArrow and NotaNaN like this.
  12. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    @cort_unity Hi, is this correct that I can't use FixedUpdate loop for my ComponentSystems until the future version of Entities be ready?
     
  13. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    In the current release of the Entities package, component systems in the SimulationSystemGroup are updated from FixedUpdate.
    In the next release of the Entities package, those systems will be moved to the Update phase of the player loop.
    In some unspecified future version of the Entities package, we will make it easier to choose which of those alternatives you'd prefer.

    Meanwhile, it is possible in even the current Entities package to manually create ComponentSystems (by adding the [DisableAutoCreation] attribute to prevent default initialization). These systems can be updated from any main-thread code you'd like -- from a MonoBehaviour in FixedUpdate, for example. It's not as clean/discoverable an experience as we'd like, but it should work.
     
  14. The-Exceptional-Bruce

    The-Exceptional-Bruce

    Joined:
    May 10, 2015
    Posts:
    29
  15. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
  16. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    The type T in [UpdateInGroup(T)] must be derived from ComponentSystemGroup, so [UpdateInGroup(typeof(UnityEngine.Experimental.PlayerLoop.FixedUpdate))] will not work (and the error message will be clarified in preview27 to make that more obvious). The workaround for now is the manual creation/update approach described in #13.
     
    Singtaa likes this.
  17. The-Exceptional-Bruce

    The-Exceptional-Bruce

    Joined:
    May 10, 2015
    Posts:
    29
    Thanks for the fast answer. you may want to throw an update to the docs here then to avoid confusion:
    https://github.com/Unity-Technologi.../master/Documentation~/system_update_order.md
     
    Zaax likes this.
  18. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    Yikes -- yeah, that document is very much out of date. I'll write up a replacement.
     
    elZach, T-Zee, psuong and 2 others like this.
  19. The-Exceptional-Bruce

    The-Exceptional-Bruce

    Joined:
    May 10, 2015
    Posts:
    29
  20. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    Here is my temporary solution for fixed time step update.

    Code (CSharp):
    1. public class MyFixedStepSystem : JobComponentSystem
    2. {
    3.     static readonly float TimeStep = 1.0f / 30.0f;
    4.     float processedTime = 0.0f;
    5.  
    6.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    7.     {
    8.         float deltaTime = Time.deltaTime;
    9.  
    10.         if ((deltaTime - this.processedTime) < TimeStep)
    11.         {
    12.             this.processedTime -= deltaTime;
    13.             return inputDeps;
    14.         }
    15.  
    16.         while ((deltaTime - this.processedTime) >= TimeStep)
    17.         {
    18.             this.processedTime += TimeStep;
    19.  
    20.             // Do my own update for fixed time step
    21.             ...
    22.         }
    23.  
    24.  
    25.         this.processedTime -= deltaTime;
    26.        
    27.         return inputDeps;
    28.     }
    29. }
     
    Orimay and Xerioz like this.
  21. diesoftgames

    diesoftgames

    Joined:
    Nov 27, 2018
    Posts:
    122
    Thanks for describing how to do this! It's probably already known, but when I do this, even though my system is running, that new ComponentSystemGroup and its systems just don't show up in the entity debugger, is there something I can do to convince them to show up?
     
  22. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    At the moment, I'm afraid not; the Entity Debugger only shows systems updated in the three built-in system group hierarchies. We have an open issue to list "orphan" systems as well, though it's not clear where/how. A potential workaround is described here: https://forum.unity.com/threads/addmanager-stopped-to-work.651058/#post-4361752
     
    diesoftgames likes this.
  23. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Hi @cort_unity, when systems auto creation will replace to non-reflection solution? Currently using reflection to auto create systems are too slow.
     
    5argon likes this.
  24. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    This transition is still in the design phase, as part of the next iteration of System Update / Multi-World improvements. My highly unofficial guess is that it's at least a few months away. Sorry, I know that's not a great estimate :/
     
  25. FROS7

    FROS7

    Joined:
    Apr 8, 2015
    Posts:
    26
    Estimates, regardless of how "great", are always welcome. Helps devs make decisions. So thank you!
     
    June1111 likes this.
  26. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,251
    @cort_unity Is there any sample code of what this might look like with JobComponentSystem? See my sample code here.
     
  27. Driiade

    Driiade

    Joined:
    Nov 21, 2017
    Posts:
    80
    Hey there.

    Do you plan to make FixedUpdate ahead of time ? So rendering can lerp between last and next simulation step ?

    This is not the case in Unity FixedUpdate, and we have to do a lot of tricks to have this.
     
  28. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Hi. I would like to know how much has been improved.
     
  29. Brammel

    Brammel

    Joined:
    Dec 25, 2013
    Posts:
    13
    Is there any information as to how "temporary" this is?
    Will this last another year or so? or is there some kind of roadmap for this?
     
    goncalo-vasconcelos likes this.
  30. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    There are no immediate plans to change which which system group is the default, or where in the Unity player loop it runs.