0

I'm trying to simulate physics manualy in a Unity 3D game. I've turned off Physics "Auto Simulation" in Project Settings and wrote this piece of code (it is more or less the unity doc sample)

private void Update()
{
    this.timer += Time.deltaTime;
    while (this.timer >= Time.fixedDeltaTime)
    {
        this.timer -= Time.fixedDeltaTime;
    controller.ApplyForces(controls);
    Physics.Simulate(Time.fixedDeltaTime);
}

}

But when I play the game, movements are lagging a lot.
In fact, I can explain it: my game runs at 120 fps. The Time.fixedDeltaTime is set to 0.01667 (60fps). So 1 out of 2 frames are not simulating physics! In other words, half of my Update calls don't enter the while loop, which produce the jump effect.

I'm sure i'm missing something... what is the recommended way to do this? Should I call Physics.Simulate in FixedUpdate?

EDIT:

As someone asked me in the comments (then deleted the comment), I'm simulating Physics manually for networking reason. With manual physics, I can do predictions and corrections. Here's a link that describes the problem

EDIT2:

Thanks to @DMGregory and his excellent answer, I figured out that the problem comes from the lack of interpolation of my player rigidbody:
InterpolationMode seems to be handled by Unity when autosimulation is set to ON, which is not my case.

So now I'm looking how to handle this myself.

Martin
  • 143
  • 1
  • 1
  • 9

2 Answers2

2

After a lot of research, I have a better understanding of this.

  1. the problem I describe is a very common problem due to unsync between frame rendering timestep and physics fixed timestep. Unity solves this automatically with the interpolationMode = interpolate of rigidbodies.

  2. when simulating physics manually, Unity do not interpolate thoses rigidbodies for us anymore. We have to do it manually, as @DMGregory suggests

  3. another option is lower fixedDeltaTime a lot to minimize desyncs, as @shingo suggests. But rendering timestep is not constant! And if the game runs at 120fps, the fixedTimestep whould be very small and CPU instensive.

  4. I highly recommand to read this article, which suggests to use Application.targetFrameRate and fixedDeltaTime to synchronise those timesteps to the same framerate.

Finally, I set the framerate to 60Hz whith those two properties: this is ok for rendering and not too intensive for CPU physics. And the game seems fluid again.

Martin
  • 143
  • 1
  • 1
  • 9
1

You are right, you need a small fixedDeltaTime value (eg. 0.01).

You can simulate physics in Update, but you'd better drag this script to the front row in Script Execution Order settings.

shingo
  • 286
  • 1
  • 3
  • But if I want my game to run 120fps, I need 0.008s. of fixed delta time, which is very, very low. I don't want physics to run that frequently, I'm sure there are some better solutions – Martin Apr 20 '22 at 08:48
  • Could you tell me why do you believe there is a better solution? You have to call Physics.Simulate to move objects, otherwise do it manually. – shingo Apr 20 '22 at 08:58
  • Maybe I'm wrong, but I have the feeling that lowering the fixed delta time will be more CPU intensive, specially with simulation correction due to networking problems (however, I'm also considering this option) – Martin Apr 20 '22 at 09:07
  • Yes, high fps is more CPU intensive. For an online game maybe you just want to synchronize the states in a low frequency. – shingo Apr 20 '22 at 09:26