Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Official Fixed timestep features coming to Entities / DOTS Physics packages

Discussion in 'Entity Component System' started by cort_of_unity, May 28, 2020.

  1. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    Hello -- my name is Cort, and I'm one of the engineers working on the Entities package at Unity.

    One feature we've had many requests for in DOTS is the ability to update an ECS system with a constant, frame-rate-independent timestep, similar to the .FixedUpdate() method on MonoBehaviours. In addition to being a critical requirement for stable, deterministic physics simulation, this feature has many applications in gameplay code as well. I'm pleased to report that fixed timestep system updates will be available in an upcoming Entities package release and wanted to give a sneak peek at how it will be exposed and what its initial capabilities and limitations will be.

    The groundwork for this feature was laid in the Entities 0.7.0 release, when we added the UpdateCallback property to ComponentSystemGroup objects. If this callback is not set (the default), system groups update as usual. If a callback is added, the system group updates its contents in a loop until the callback returns false.

    In the same release, we added the FixedRateUtils class, which contains some sample callbacks intended to be used with this feature. One of them, FixedRateUtils.FixedRateCatchUpManager, essentially configures the system to run like FixedUpdate(): when enabled, the system group temporarily overrides World.Time.ElapsedTime and World.Time.DeltaTime for the duration of its update, and then updates as many times as necessary to "catch up" to the actual elapsed time. The original ElapsedTime and DeltaTime values of World.Time are restored just before the system group update ends.

    In an upcoming release (tentatively Entities 0.12.0-preview), we'll add a new system group that uses this catch-up feature by default. A new ComponentSystemGroup will be added to default DOTS Worlds (tentatively called the FixedStepSimulationSystemGroup). It will update at the beginning of the SimulationSystemGroup (after the BeginSimulationEntityCommandBufferSystem, but before any other systems in the group). It will use FixedRateCatchUpManager, with a default timestep of 1/60th of a second. It will contain begin/end ECB systems so that systems in the group can instantiate/destroy entities and make other structural changes.

    In a subsequent release of the DOTS physics packages, physics systems will be modified to update in the new FixedStepSimulationSystemGroup instead of the SimulationSystemGroup. This may require application changes: any user systems that currently order themselves relative to the physics systems will need to update their ordering constraints and/or their system groups.

    DOTS Physics systems will refer to World.Time.DeltaTime in their simulation code, instead of UnityEngine.Time.fixedDeltaTime. This puts the timestep used by the physics system completely under the control of its parent system, and breaks the direct dependency on UnityEngine.Time.

    If you have any questions about the plan, let me know in the comments. Here's a few FAQs:

    Q: Can I override the default fixed timestep value?
    A: Yes, the timestep is a property on the FixedStepSimulationSystemGroup. Changing this property has the same effect for the group as changing UnityEngine.Time.fixedDeltaTime does for MonoBehaviour fixed updates: the next fixed-timestep group update will occur at LastUpdateTime + newTimestep.

    Q: What systems will update in the fixed-timestep system group by default?
    A: Currently, only the physics systems will move into the fixed-timestep system group. This will happen in a release of Unity Physics following the Entities release where the new group is available.

    Notably, the TransformSystemGroup (which is responsible for computing LocalToWorld/LocalToParent matrices and adding/removing Parent/Child relationships) will continue to update in the main SimulationSystemGroup. Systems inside the fixed-timestep system group should not rely on these Transform components having been updated by the next fixed update because the next fixed update might be a catch-up update in the same frame!

    For example, if inside the fixed-timestep system group, you add a Parent component to make entity B the parent of entity A, you should not expect entity B to have the Child component by the next fixed update. The Child component is added by the TransformSystemGroup, which is only updated after the fixed-timestep system group has finished all of its updates for the current display frame.

    Dynamic rigid bodies affected by physics should present no problems since they read from and write directly to Translation and Rotation components of root-level entities.

    Q: Does the FixedStepSimulationSystemGroup support anything like the RigidBodyInterpolation feature on RigidBody components, to provide smoother motion at low simulation tick rates by interpolating/extrapolating the transforms of simulated objects based on previous fixed-timestep results?
    A: No. We do not support this feature. Systems running after the fixed-timestep system group (including the rest of the variable-timestep simulation group and the presentation group) will only see the results of the most recent fixed-timestep system group update. If the display frame rate is higher than the fixed-timestep simulation rate, the motion of simulated objects may appear jerky.

    The simplest workaround for this issue is to keep the simulation rate and the display rate as close as possible, either by artificially capping the display rate, or manually decreasing the fixed timestep value.
    In some cases, applications may want to disable the “catch-up” semantics of the fixed timestep group entirely, and have it update exactly once per display frame; this is an simple change to make during application bootstrap time. The fixed timestep system group can either continue to use a constant deltaTime, or it can fall back on the default, frame-rate-dependent deltaTime. Each approach has pros and cons for the application to consider:

    Fixed Timestep with catch-up
    PRO:
    Simulation determinism. Simulation stability. Matches familiar FixedUpdate() behavior. Simulation time tracks “real” elapsed time.
    CON: Jerky motion if display rate > simulation rate. Less predictable overall frame rate due to normal frame time fluctuation (even with a ~60fps display rate, the fixed timestep group will update zero times in some frames, twice in others). Running the simulation >1 times per frame can become expensive.

    Fixed Timestep without catch-up
    PRO:
    Simulation stability. Predictable frame times (exactly one simulation tick per frame). No jerkiness at high display frame rates.
    CON: Simulation rate is locked to display rate; large changes in the display rate will cause the simulation to run correspondingly faster / slower. Simulation’s elapsed time will drift from “real” elapsed time. This approach is best when a stable frame rate can be guaranteed.

    Variable Timestep (fixed timestep disabled)
    PRO:
    Predictable frame times (exactly one simulation tick per frame). No jerkiness at high display rates. Simulation time tracks “real” elapsed time.
    CON: Potential simulation instability (frame rate spikes -> large deltaTime). Non-deterministic simulation.​

    Q: Can I read / process user input in fixed updates?
    A: Yes, if proper care is taken to make sure that input events are applied to the correct simulation tick(s).
    Polling an input device returns events that occurred during a particular window of “real” time (since the last poll occured). Without fixed timesteps, this is the same window of time the application is about to simulate, so input events can be consumed immediately. When fixed timesteps are enabled, however, the simulation window no longer necessarily corresponds with the input-polling window; without proper care, input events may be processed multiple times, or processed too early, or ignored entirely. Developers who have worked with input processing in MonoBehaviour.FixedUpdate() may be very familiar with these challenges.

    To avoid these problems, input events must be timestamped and bucketed by which simulation frame they should apply to. These events may need to be buffered across multiple display frames until the fixed-timestep system group processes the appropriate simulation tick.

    We plan to release sample scenes in the Entities package that demonstrate correct input processing when fixed timesteps are enabled.
     
    mtka, Alic, Kmsxkuse and 25 others like this.
  2. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,008
    Hi. I implemented my own FixedSimulationGroup which is injected to FixedUpdate of PlayerLoop.

    Is there any reason for that Unity not using just existing FixedUpdate loop? I think that it is more simple and can easily be integrated with existing PhysX based components (hybrid).
     
    jdtec likes this.
  3. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    880
    Sounds fantastic, thanks for update.
     
  4. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    That's a fair question; certainly the easiest way to get "familiar FixedUpdate()-style behavior" would be to just tick ECS systems from FixedUpdate().

    One requirement that pushed us towards the current solution was the need to support the feature in DOTS Runtime / Project Tiny, where there is no UnityEngine functionality to lean on.

    We also wanted more flexibility than the existing FixedUpdate() functionality offers. The FixedStepSimulationSystemGroup is meant to provide a reasonable default, but we also wanted the ability for applications to customize (or disable) the fixed timestep system group, or to run the whole simulation with a fixed timestep (including the physics sim), or things we haven't thought of yet.

    Putting the fixed timestep mechanism into the Entities package and under application control addressed both requirements.

    To address your use case of interacting with PhysX objects in DOTS, I can't make any specific promises, but we do have some improvements to the DOTS player loop manipulation code in mind that would make it easier for applications to configure which system groups are added to the player loop (and where).
     
    JesOb, NotaNaN, Orimay and 2 others like this.
  5. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    Seems like we will need to choose between:

    1. Jerky motions to have proper frame-rate independent simulation
    2. Frame-rate dependent simulation to not have jerky motions

    Isn't it possible to have something that supports something like Rigidbody Interpolation at all?
     
    Opeth001 likes this.
  6. I think that's a physics implementation detail and thus not subject of this fixed timestep system. The physics systems probably will, or already do that.

    My question is, why the odd default? I mean the built-in PhysX system runs on 1/50. Is there any consideration behind it? Or do you expect to be the 60FPS the standard and don't expect that the physics would handle the interpolation? (Well, maybe the above question isn't that clean cut after all?)

    Would it be possible to define our own fixed-step simulations (multiple) on different fixed time-step? Or it is not the plan at first?
     
  7. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    It doesn't seem like as previously stated:
    But I may have misunderstood the situation.
     
  8. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    @Lurking-Ninja is correct that an interpolation feature is beyond the scope of the Entities-related changes here, and might be better exposed as a feature of the physics package.
    @brunocoimbra is also correct, the DOTS Physics packages do not support this feature yet. It's definitely on their radar and being discussed, but once again, I can't make any specific promises about features or timelines on that front.
    I have seen reports (e.g. this tweet) that nobody at Unity can remember why the default fixed-update rate is 50 Hz, and can confirm that this has been my experience as well. The most plausible (but still unsubstantiated) theory I've heard is that it was originally targeting the PAL 50Hz video standard. Literally everybody we consulted internally agreed that a 60Hz default would make more sense in 2020. Most of them were also in favor of changing the MonoBehaviour.FixedUpdate() default to 60Hz as well, but agreed that it would cause too many breaking changes in existing projects. Fortunately...
    ...yes, you can change the timestep value of the group with a single line of code (something like group.Timestep = 1.0 / 50.0). You can also define your own fixed-timestep system groups, or customize/disable the one we provide by default; the core feature is available to any ComponentSystemGroup.

    Having multiple fixed-timestep groups running at different rates in the same frame is possible, but tricky; if implemented naively, they won't interleave their updates the way you might expect. This could potentially cause problems if the outputs of one group feed into the inputs of the other. The application could implement proper interleaving behavior in a more complex FixedRateManager; in theory you could attach an individual Timestep and LastUpdateTime on every system in a group, throw them into a priority queue, and figure out exactly which systems need to tick (and in which order) for a given "real" elapsed deltaTime. But currently that's left as an exercise for the reader.
     
    gtzpower, NotaNaN, quabug and 5 others like this.
  9. KwahuNashoba

    KwahuNashoba

    Joined:
    Mar 30, 2015
    Posts:
    110
    In other words, all components used in building physics world and being exported as result will be updated from "catch up" to "catch up" update?

    Does this still apply if the one is using manual InputSystem update? If I remember correctly, somewhere on forum has been mentioned that update provides an access to a buffer of all the input that occurred since the last call, so having that in mind it sounds that there should not be an issue, unless someone desires to have "less precise" update relaying on frame-rate rather then real-time update.
     
  10. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    In any case, rigidbody interpolation is a fairly simple feature to implement:
    • remember current & previous pos/rot of the transform at every fixed update
    • at every variable update:
      • float t = timeSinceLastFixedUpdate / fixedTimeStep;
      • pos = math.lerp(prevFixedUpdatePos, currentFixedUpdatePos, t)
      • rot = quaternion.slerp(prevFixedUpdateRot, currentFixedUpdateRot, t)
    Or something like that. Someone could probably release a simple system that does that soon after the fixedUpdate feature lands
     
    Last edited: May 31, 2020
  11. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
    Another possible decision factor is that you can't have exactly 60 Hz. Timestep would be 0.01666667, which translates to 59.99999 Hz. Physics must be as deterministic as possible, and you can achieve exactly 50 Hz with timestep = 0.02.

    Not surprisingly, many monitors with "60 Hz" refresh rates are actually 59.94 Hz and sometimes even plainly displayed as 59 Hz. I'd be against setting the physics default rate to 60 Hz because calculations won't be as precise as with 50 Hz, and in practice you'll never have a 1:1 correspondence with the monitor refresh rate. For example, think that just drifting one frame out of those 60 frame per second mean one visual stutter per second.

    In my opinion a correct solution forcefully requires interpolation. Choose a timestep that doesn't involve periodic decimals for precise calculations, and let the interpolation provide the visually smooth results.
     
    Last edited: Jun 1, 2020
  12. Zeffi

    Zeffi

    Joined:
    Nov 18, 2017
    Posts:
    24
    Interesting approach! Thanks for the update on this, and, despite what I am saying below, I like the approach and transparency.

    I do admit that it seems a lot more complicated than before (pre-DOTS), though.

    And of the options you list, I will basically have to pick the last one. Frame rate affecting simulation speed is an absolute no-go and feels like a throwback to old game design that's really, really bad (like old racing games that are so difficult to play at current framerates), while jerykness doesn't seem ideal either.

    That said, having the option is good, because the option means entirely different use caes will work. Single player games that probably don't care for determinism (as there's no need to sync anything) will probably default to the third option, won't they? Or am I misunderstanding something here? I'd love to hear if my logic has a huge flaw!

    I can't imagine a single scenario *in a single-player game* where I would even care for determinism, especially if the cost for it is "frame rate affects simulation speed".
     
  13. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    • We have separated our server / client logic into a Server world and a Client world.
    • A game client will be able to run both worlds simultaneously.
    • Each world would preferrably be able to have individual fixed frame rates (server update rate can be much lower)
    Would this be possible with the planned approach? The FixedStepSimulationSystemGroup would have be non-static for that to be supported, is that the case? Or is it a static field, used for all instances of FixedStepSimulationSystemGroup?
     
  14. lijianfeng

    lijianfeng

    Joined:
    Sep 8, 2015
    Posts:
    54
    please don't do that ,in order to fixedupdate or separate simulation and presentation ,I just need to set world.quite update to true ,and update the three group :initialize,simulation,present my self。Actually,I have made a game use DOTS this way ,and it worked fine.
    Code (CSharp):
    1.     public void Update()
    2.     {
    3.         if (!LoadComplete)
    4.             throw new Exception("BattleWorld has not been Initialized ,check value: BattleWorld." + nameof(LoadComplete));
    5.  
    6.         m_AccumulateTime += UnityEngine.Time.deltaTime;
    7.         m_World.QuitUpdate = false;
    8.  
    9.  
    10.         while (m_AccumulateTime > ConstantsOfWorld.FixedDeltaTime)
    11.         {
    12.             m_InitializationSystemGroup.Update();
    13.             m_SimulationSystemGroup.Update();
    14.             CheckEnd();
    15.             m_AccumulateTime -= ConstantsOfWorld.FixedDeltaTime;
    16.         }
    17.  
    18.  
    19.         m_World.GetExistingSystem<TransformPresentationSystem>().DeltaTime = m_AccumulateTime;
    20.         m_PresentationSystemGroup.Update();
    21.         m_World.QuitUpdate = true;
    22.     }
     
    Pleija likes this.
  15. lijianfeng

    lijianfeng

    Joined:
    Sep 8, 2015
    Posts:
    54
    why your guys spend time do the meaningless thing,when do you fixed the world memory leak problem. until now,there is even not exist a simple way to convert array of prefabs to entity prefabs... :confused:
     
  16. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    You can disable the fixed timestep "looped update" behavior on the FixedStepSimulationSystemGroup with a single line of code, at which point it will behave just like a regular ComponentSystemGroup. The manual init/sim update approach you describe would still work at that point.
     
    florianhanke likes this.
  17. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    The FixedStepSimulationSystemGroup is instantiated as part of the default World initialization. If you're using default world initialization on both the client and server Worlds, you'll get a unique instance of the fixed timestep group in each World. If not, it should be straightforward to instantiate the group in custom Worlds, or create your own group with similar update semantics. The FixedStepSimulationSystemGroup doesn't rely on any special internal magic to implement, only public Entities features; it's 45 lines of new code in DefaultWorld.cs, most of which are comments :)

    All fixed-timestep-related state (last update time, timestep value, etc.) in the group is stored per system instance; it's not static.
     
    Singtaa likes this.
  18. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    Except 0.2 isn't really a precise floating point number, either. The literal 0.2f will actually be 0.200000003 in single precision IEEE754, aka float.
     
    cort_of_unity likes this.
  19. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
    What about 0.02f?
     
  20. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    699
    Ooops, good find, same problem, but the error is outside the Mantissa limit, so it doesn't really show up in float.
     
    Edy likes this.
  21. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    789
    I testet in an online converter, it was: 0.0199999995529651641845703125
     
  22. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
    That looks like a double to me, not a float.

    EDIT: Anyways you're right @Thygrrr, 0.02f doesn't mean anything different in precision. I've just tested this code:
    Code (CSharp):
    1. float f = 0.0f;
    2. for (int i=0; i<50; i++) f += 0.02f;
    3. Debug.Log(f);
    4.  
    And the result is 0.9999996, not 1.

    If all, this enforces the need for visual interpolation. Without it, not even setting the default physics rate to ~60Hz could guarantee reasonably stutter free motion.
     
    Last edited: Jun 3, 2020
    goncalo-vasconcelos likes this.
  23. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    954
    The floating point precision problem.
    A good way to play around with it: https://www.h-schmidt.net/FloatConverter/IEEE754.html

    Regarding the imprecision in time steps, it doesn't realy matter as long as you use a float value relatively. Where it starts to get problematic is when we apply human measurement logic and expect something to be 1. But for Physics, as long as the relative time steps are the same there shouldn't be a problem.

    It's an interesting topic but for physics determinism, timestep is a non-issue, well, as long as the float fixedDeltaTime is the same on every architecture which IS a big factor and I'm only describing it as non-issue because Unity will handle this problem for us.
    The biggest issue in physics determinism is using RNG for solvers like a contact solver. New Physics frameworks are now avoiding RNG for that specific reason. For offline calculations RNG would still be valid, it's just not usable for anything networked.

    On topic:
    I'm pretty happy with the new PlayerLoop logic, Time and UpdateCallback. Implementing any kind of time stepping is now possible on a global scale or even in ordered system groups and not as annoying and problematic with scaling than in MonoBehaviours.

    I'd just like more full examples and tests on your docs website. Just look at this page: https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.html
    or
    https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.SetPlayerLoop.html
    Pretty much zero info.

    Gathering the info how to do things, I needed to go through the ECS package source code, which has a staggering amount of cool tests you can learn from by the way.
    What I still don't understand is the purpose of PushTime and PopTime. They are used in the FixedRateUtils and TBH I still don't get what this actually does compared to just SetTime.
     
  24. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    98
    The reasoning was that the core operations are "set some new time+timestep for some portion of my frame" and "restore the original time+timestep". Minimally, SetTime would probably be sufficient for both cases, but exposing PushTime/PopTime instead saves the caller from having to save off the original time value to restore later. And since you could potentially have a FixedRateUtils group inside another FixedRateUtils group, you might have several "original" values to restore in sequence; so, a stack.
     
  25. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    Last time (it's been a while) I checked FixedRateUtils, there wasn't any failsafe for CPU starvation if you used the fixed timesteps with it. If this is still the case, I do hope Unity will address it in some way. I do get it does bring up issues with determinism but then again, so does your client freezing when not being able to keep up..
     
  26. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    This is something I've been meaning to look into a little in the Physics package, but Glenn Fiedler wrote a really insightful article titled Fix Your Timestep! where he explains how to get rid of the stutter that's caused by a framerate < fixed update. This could be included as a fix on the physics package itself where it correctly interpolates the transform components based on the physics state that's maintained. This does mean that the physics package will be maintaining its own copy of the transform data and there has been some concern expressed over this data duplication in other threads as well.

    I'll be honest and say I quite like this approach, but it comes with the added complexity that might not be suited to everybody's needs. I think one thing that DOTS is unearthing is just how complex an engine can be because people are now able to access more in-depth data which is leading to some level of confusion for those who treated everything more like a black box.
     
  27. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I feel like this new DOTS physics setup is pretty much the same as the old monobehaviour physics setup.

    In monobehaviour physics, if you move a transform.position and then try to access the rigidbody.position later in the same frame, the rigidbody.position will not have moved like the transform.position. It'll stay different until either the next frame or a manual sync of transforms. If I'm not mistaken, interpolation also only affects the transform.position and not the rigidbody.position. So the monobehaviour physics does keep two separate transform datas too. It just tries to conceal it more, which was the source of many headaches for me when I wasn't aware of how things really worked

    In the end they both do the same thing, and the out-of-the-box fixed timestep DOTS physics would be a direct equivalent of monobehaviour physics with interpolation turned off on rigidbodies. All that is needed is the addition of an interpolation system like this, and you'll end up with the same functionality as old physics
     
    Last edited: Jun 10, 2020
    NotaNaN and Nothke like this.
  28. Kleptine

    Kleptine

    Joined:
    Dec 23, 2013
    Posts:
    274
    I appreciate this direction. There's no one-true way to avoid stutter -- each game has to make the choice for itself.

    Interpolation is attractive, but requires an extra frame of input latency, which is not great for many certain games (ie. VR or competitive shooters). Extrapolation solves that, but can create jutter via mispredictions.

    Additionally, whether or not VSync is enabled is critical -- if VSync is on, even variable time steps will create jutter if the monitor's frame rate is not matched with the simulation rate. The monitor will always present 60Hz, but if the game is calculating time steps at any other rate (as the frame time fluctuates), you're going to see jutter.
     
  29. Roycon

    Roycon

    Joined:
    Jul 10, 2012
    Posts:
    50
    Opeth001 likes this.
  30. JoNax97

    JoNax97

    Joined:
    Feb 4, 2016
    Posts:
    611
    I think it's because that's coupled with the UnityEngine runtime. They're making everything work with a new DOTS runtime (currently used by project tiny)
     
    KwahuNashoba likes this.
  31. tommox86

    tommox86

    Joined:
    Apr 30, 2015
    Posts:
    88
    newbie here, how to use FixedStepSimulationSystemGroup ? small code example would be much appreciated
     
  32. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    @tommox86
    FixedStepSimulationSystemGroup
    is part of the Entities 0.12.0-preview release that isn't yet available from what I can see. As soon as it's available you should be able to play around with it, but it will essentially entail something like the following:

    Code (CSharp):
    1. [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    2. class YourSystem: SystemBase
    3. {
    4.     //system code here
    5. }
     
  33. H-Alex

    H-Alex

    Joined:
    Oct 2, 2012
    Posts:
    26
    Hey @cort_of_unity, thanks for the in depth insight on that. Our current setup is that we have a server running a fixed simulation at around 10 fps (fixed timestep with catchup). The client is running the same for his client side prediction, but it is synchronized and will slow down / tick faster (without changing the fixed timestep) in case it needs to resync with the server.

    Right now I've got my own FixedSimulationGroup that does all of the above, and which is built around the new ComponentSystemGroup.UpdateCallback.

    I'm in the middle of adding physics and I'd like to make it tick on my custom FixedSimulationGroup (which may behave slighly differently of the one that will be builtin).

    - can this be done with the current release?
    - what about the next release? what would be easier / more robust?

    - why such code in StepPhysicsWorld.cs?

    Code (CSharp):
    1. #if !UNITY_DOTSPLAYER
    2.             float timeStep = UnityEngine.Time.fixedDeltaTime;
    3. #else
    4.             float timeStep = Time.DeltaTime;
    5. #endif
    - somewhat unrelated, or maybe not... the StepPhysicsWorld System is taking a whole 3ms on my machine as soon as I add one single rigidbody. Is that expected behaviour? Does it scale well?

    - is there an ETA for 0.12 + updated physics (I might have missed that from the thread)

    Thank you for your help, that's very much appreciated!
    Best,
     
  34. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Will the physics systems be refactored to optimize for iterating multiple times in a frame? Right now physics step/build flow all together is pretty expensive in terms of main thread usage. If this requires running the whole step/build flow multiple times and isn't refactored in some areas it's going to be a pretty big hit.

    I'm also curious why not an option for an actual variable timestep with physics always ticking once per frame? I would ask at least make it possible without source level modifications.
     
  35. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Or is that what option 3 is? Maybe I was just reading it wrong. I was thinking specifically the variable timestep is some multiple of the fixed timestep. So you accumulate time to sort that out. Which is a different thing then just going by real elapsed time only.
     
  36. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Initially, there will be no changes. The issue is that someone can (and in fact should) put game code that interacts with physics into the same system group. It is the only way to guarantee that you process contact events when they happen, for example. So in the case something like a contact event destroys some rigid body, we of course need to rebuild whatever tree the body was in. That said, I think either way we would love to get some real-world examples in hand that illustrate unacceptable main thread overhead that is unique to physics (as distinct from just general job scheduler overhead, for instance). Feel free to ping me or @steveeHavok directly, or share in the physics sub-forum.

    You are correct this is the third option, and it can be done without any source modifications.
     
  37. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    So how would you configure variable timestep in Entities 0.13?
     
  38. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    954
    Where can I find the sample referenced in the entities 12 changelog?
    It's called FixedTimestepSystemUpdate sample scene there.
     
  39. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
    PutridEx likes this.
  40. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Interpolation as it's normally handled makes velocity a write only construct which really sucks.

    I think what is better is some notion of real and effective motion data. For position, rotation, and velocity. I like the idea of that being very explicit and it's always what it is. You never have to ask has this been interpolated. Real never is and effective always is, at all times everywhere.

    I also don't see a reason to involve the transform system for dynamic and kinematic bodies. They don't have hierarchy. I can't think of any reason why not to just update LocalToWorld in export physics. With that and real/effective values I think you can always have a consistent view of the data. No gap between physics and the transform group where it's not consistent.

    - Build the physics world
    - Game logic changes to physics bodies
    - step/export physics world.
    - remaining game logic. Physics data and transforms are synced at this point
    - end frame physics system

    This gets a bit beyond the topic of this thread but the transform and rendering sytsems have forced sync points, so there is good reason to not include them if you don't have to. Why we don't stack rendering components on physics bodies. If you remove the transform system from the picture for dynamic/kinematic bodies it's one more DOTS forced sync point removed.
     
  41. Scorr

    Scorr

    Joined:
    Jul 2, 2013
    Posts:
    73
    Seems this is still the case in 0.4.1
    The bottom one refers to World.Time so that is correct, but afaik UNITY_DOTSPLAYER isn't usually enabled (only meant for project Tiny?), so by default it is still incorrect if your fixedDeltaTime doesn't match the update rate. Shouldn't this be using World.Time regardless?

    Maybe this is an oversight since it's being moved to a fixedrate group (and thus should be in sync with fixedDeltaTime?), but it'll be incorrect if you are manually stepping physics at a different rate, for example in custom worlds.
     
    sietse85 likes this.
  42. H-Alex

    H-Alex

    Joined:
    Oct 2, 2012
    Posts:
    26
    Hey @cort_of_unity, could you update us on the current status of the feature?
    Best
     
    NWHCoding likes this.
  43. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    862
    What if I want to have an update that happens before FixedStepSimulationSystemGroup but at a fixed time step? Would that be possible?

    Would the code below update after FixedStepSimulationSystemGroup using a fixed rate?

    [ExecuteAlways]
    [UpdateInGroup(typeof(SimulationSystemGroup), OrderLast= true)]
    [UpdateAfter(typeof(BeginSimulationEntityCommandBufferSystem))]
    public class lateFixedUpdate: ComponentSystemGroup
     
    Last edited: Aug 15, 2020
  44. sietse85

    sietse85

    Joined:
    Feb 22, 2019
    Posts:
    99
    I hit this problem today in my network code. Having a networktick rate 1 / 30 and that system doing 1 /60 gives troubles of stuff not syncing correctly. In other words i want to move all the physics systems into my new fixedtimestep group.
     
  45. turick00

    turick00

    Joined:
    Jul 14, 2020
    Posts:
    31
    I'm sifting through this thread and older info online. I was excited to learn that I can access the fixed time in the simulation group. I just wanted to make sure I'm doing this correctly. I'm just checking these values in different systems:

    Code (CSharp):
    1. Debug.Log("fixed time: " + UnityEngine.Time.fixedTime.ToString());
    2. Debug.Log("fixed delta time: " + UnityEngine.Time.fixedDeltaTime.ToString());
    3. Debug.Log("in fixed time step? " + UnityEngine.Time.inFixedTimeStep.ToString());
    The output looks roughly like this:

    fixed time: 6.6
    fixed delta time: 0.02
    in fixed time step? false


    This even seems to work in the initialization group. Should the `inFixedTimeStep` bool being false be concerning at all? Also, I've noticed in the log that sometimes the value doesn't actually update, as in, there can be 3-4 log messages saying `fixed time: 6.6`. Is that normal? Do I need to manually detect times when the loop executes again but the time hasn't advanced?
     
  46. pverflow

    pverflow

    Joined:
    Jun 4, 2019
    Posts:
    7
    ok what would be the concrete way to set the timestep in FixedStepSimulationSystemGroup. I dont understand much code so please a direct solution answer would go a long way :)

    because FixedStepSimulationSystemGroup.Timestep = 1/ 90; doesn't seem to work....
     
  47. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    Looks like you might be doing an integer division. 1/90 is a division between two integers, which would likely end up with 0 as the result. Try 1/90f. The f indicates that the 90-value in the division is a float (decimal type variable), which will give you the correct value. It's typically enough to put the f on the 90 in this case.
     
    pverflow likes this.
  48. Morps_QC

    Morps_QC

    Joined:
    Apr 18, 2018
    Posts:
    1
    After some searching, I believe this is the single line of code that @cort_of_unity kept referring to:
    World.GetExistingSystem<FixedStepSimulationSystemGroup>().RateManager = new RateUtils.VariableRateManager();
     
    Mayumichi likes this.