Search Unity

How to do frame-rate independent physics in DOTS

Discussion in 'Entity Component System' started by Simoyd, Mar 11, 2020.

  1. Simoyd

    Simoyd

    Joined:
    Apr 19, 2013
    Posts:
    15
    I'm trying to get my physics to be frame-rate independent in DOTS. It seems that both Unity.Physics and Havok.Physics use UnityEngine.Time.fixedDeltaTime, but process physics every graphics frame. The result of this is that the higher the framerate is, the faster things move around given the same PhysicsVelocity values. An easy way to see this is to simply increase the "Fixed Timestep" in edit->project settings->time, so that it doesn't match your framerate.

    from "Unity.Physics\ECS\Systems\BuildPhysicsWorld.cs":
    upload_2020-3-10_20-52-19.png

    I tried defining UNITY_DOTSPLAYER in edit->project settings->Player->Other Settings->Scripting Define Symbols, but this seems to break many other things. Is this a bug? should it be using DeltaTime in all cases?

    The DOTSSample doesn't have this issue on the player because the player controllers are using scripted ray/collider cast physics, not Unity.Physics. I'm not sure if there's a different sample I can reference or something.

    Is there an easy way with DOTS to get frame-rate independent physics? Any help would be greatly appreciated.
     
    unity_m0YR-bwAdMHOKw likes this.
  2. Games4Stream

    Games4Stream

    Joined:
    Jan 11, 2020
    Posts:
    5
    Right now there is no actual solution for the problem. The easiest workaround for me was to use the following code. As you can see, it is based on another forum post. I had to make some adjustments though to get it to work.

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Physics.Systems;
    3.  
    4. // Source: https://forum.unity.com/threads/unity-physics-discussion.646486/page-18#post-5027081
    5.  
    6. [UpdateBefore(typeof(BuildPhysicsWorld))]
    7. public class PrePhysicsSetDeltaTimeSystem : ComponentSystem
    8. {
    9.     public bool isRealTimeStep = true;
    10.     public float timeScale = 1;
    11.     public float previousDeltaTime = UnityEngine.Time.deltaTime;
    12.  
    13.     protected override void OnUpdate()
    14.     {
    15.         previousDeltaTime = UnityEngine.Time.deltaTime;
    16.  
    17.         if (isRealTimeStep)
    18.         {
    19.             UnityEngine.Time.fixedDeltaTime = UnityEngine.Time.deltaTime * timeScale;
    20.         }
    21.         else
    22.         {
    23.             UnityEngine.Time.fixedDeltaTime = UnityEngine.Time.fixedDeltaTime * timeScale;
    24.         }
    25.     }
    26. }
    27.  
    28. [UpdateAfter(typeof(ExportPhysicsWorld))]
    29. public class PostPhysicsResetDeltaTimeSystem : ComponentSystem
    30. {
    31.     public PrePhysicsSetDeltaTimeSystem preSystem;
    32.  
    33.     protected override void OnCreate()
    34.     {
    35.         preSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<PrePhysicsSetDeltaTimeSystem>();
    36.     }
    37.  
    38.     protected override void OnUpdate()
    39.     {
    40.         UnityEngine.Time.fixedDeltaTime = preSystem.previousDeltaTime;
    41.     }
    42. }
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    0.7 has support for fixed update groups
     
    Enzi likes this.
  4. Simoyd

    Simoyd

    Joined:
    Apr 19, 2013
    Posts:
    15
    Thanks for these guys. The delta time systems seem to be exactly what I want.
     
  5. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    90
    I saw that on the cnagelog, any hints on how to use it? I did not understand it reading the docs.
     
  6. Simoyd

    Simoyd

    Joined:
    Apr 19, 2013
    Posts:
    15
    ShadLady and Games4Stream like this.
  7. rochg

    rochg

    Joined:
    Jan 14, 2017
    Posts:
    4
    In the simplest case you can do...

    Code (CSharp):
    1.  
    2. FixedRateUtils.EnableFixedRateWithCatchUp(World.GetOrCreateSystem<SimulationSystemGroup>(),
    3.                                     UnityEngine.Time.fixedDeltaTime);
    4.  
    ... which will get the physics (and the rest of the simulation group) running at a fixed framerate. Once this is done an ECS object reliably falls at the same rate as an equivalent MonoBehaviour object.

    I think the downside is that the whole simulation group is now running at a fixed frame rate so you won’t get interpolation of physics objects in the non-fixed frames, and if you have other systems in that group they will also be fixed rate.

    I haven’t experimented any further yet. AFAICS there is still no easy way to get a fixed rate physics simulation with interpolated movement and without the need to get involved with adjusting the system groups. Has anyone else got any further?
     
    schaefsky and Games4Stream like this.
  8. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    90
    Would I just put that in any Awake() or Start() of some Monobehavior?
     
  9. rochg

    rochg

    Joined:
    Jan 14, 2017
    Posts:
    4
    I put it in one of my systems - not really a great place, just somewhere quick and dirty to try it out. I found putting it in OnCreate() sent Unity into an infinite spin, but delaying it until the first OnUpdate() worked.

    public class PlayerSystem : ComponentSystem
    {
    private bool once = false;

    protected override void OnUpdate()
    {
    if (false == once)
    {
    FixedRateUtils
    .EnableFixedRateWithCatchUp(World.GetOrCreateSystem<SimulationSystemGroup>(),
    UnityEngine.Time.fixedDeltaTime);
    once = true;
    }
    }
    }

    I didn't persevere with this for now because I didn't want my other simulation world systems to have the fixed rate and didn't want to give the time to experimenting with moving systems around until it was clearer how Unity expects this all to work in the end. So, for now I've gone back to hacking UnityEngine.Time.fixedDeltaTime either side of the physics systems.
     
    edalbeci and schaefsky like this.
  10. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    90
    Thank you, I finally got around to try it, and my camera follow system at long last is smooth again.
    The old FixedUpdate() system update method broke for me somewhere around last summer.
    So I guess this is not the way it is supposed to be used, but it makes my game so much smoother again I love it!