Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Confused about practical use of substepping Unity Physics
#1
I just got done debugging an awful bug related to sub-stepping Unity physics. 

According to http://obi.virtualmethodstudio.com/tutor...aters.html, substepping Unity physics is necessary when using more than 1 substep and performing accurate collisions with Rigidbodies.


I have a game where the player controls a quadcopter drone. To simulate the propellers of my drone, I apply an upward force in FixedUpdate. I have the drone calibrated such that the force applied in FixedUpdate is equal to the mass of the drone, such that under normal circumstances, the drone perfectly hovers in place.

I've been messing around with ObiRope, and got it working somewhat well, but I found that whenever I had an Obi rope in the scene, my drone was no longer capable of hovering in place. I thought maybe the mass of an attached rope was pulling the drone down. So I started decoupling the rope and the drone. I got to a point where the two were in completely separate GameObject hierarchies, nowhere near each other in the scene, and still the presence of the rope in the scene was causing my drone to be incapable of hovering.

Then I started playing around with the ObiFixedUpdater I was using for my rope and I found that if I disabled "Substep Unity Physics" on the updater, my drone was magically able to hover again! I dug into the source code for ObiFixedUpdater and found that it directly calls https://docs.unity3d.com/ScriptReference...ulate.html. So I began to realize the issue with my drone. My drone was falling because Physics was being simulated, including gravity forces, but my FixedUpdate was not being called during this extra Physics.simulate.

I searched these forums and found this post: http://obi.virtualmethodstudio.com/forum...ml#pid6497 where it is suggested to use the ObiUpdater.OnBeginStep callback instead of FixedUpdate to apply forces. So this leaves me confused again and with more questions:

  • Doesn't calling Physics.Simulate in addition to the normal unity physics update loop essentially cause Unity's physics simulation to proceed faster than realtime?
  • Am I supposed to disable Physics.autoSimulation to use substepping with a FixedUpdater?
  • Wouldn't I effectively get the same result from reducing Unity's physics timestep rather than doing the complicated process of substepping Unity physics and then replacing all of my FixedUpdate calls with OnBeginStep callbacks? (Or am I supposed to have FixedUpdate in addition to OnBeginStep?)
Physics substepping seems barely mentioned in passing in http://obi.virtualmethodstudio.com/tutor...aters.html, and it leaves all of these questions unaswered in my mind.
Reply
#2
Hi there,

Quote:Doesn't calling Physics.Simulate in addition to the normal unity physics update loop essentially cause Unity's physics simulation to proceed faster than realtime?

Nope, as you pass in the amount of time simulated by the call. Calling Physics.Simulate(0.2) advances the simulation the same amount of time as calling Physics.Simulate(0.1) twice.

Quote:Am I supposed to disable Physics.autoSimulation to use substepping with a FixedUpdater?

No, this is automatically done by the FixedUpdater. Whenever substep Unity physics is enabled, auto simulation is disabled, as Physics.Simulate() is called explicitly. Also, Keep in mind this quote from Unity's docs: https://docs.unity3d.com/ScriptReference...ulate.html
Quote:Calling Physics.Simulate does not cause FixedUpdate to be called.

Quote:Wouldn't I effectively get the same result from reducing Unity's physics timestep rather than doing the complicated process of substepping Unity physics and then replacing all of my FixedUpdate calls with OnBeginStep callbacks? (Or am I supposed to have FixedUpdate in addition to OnBeginStep?)

There's two reasons why we have an explicit "substep" parameter instead of just relying on using a smaller 'global' fixed timestep:

- We can decouple Obi's update from Unity's own physics update. This is important when you have actors (ropes, cloth, etc) that need to be updated using a smaller timestep than the rest of the physics.

- Collision detection (finding potential contacts) is performed only once per step, and amortized over all substeps in the frame. This means that we can perform many substeps, without paying the cost of collision detection for each one. This makes substeps much more efficient than using a smaller global timestep, and more efficient than iterations, as they improve convergence a lot more while being only slightly more expensive. This idea is based on the "small steps for physics simulations" academic research article: http://mmacklin.com/smallsteps.pdf

So, reducing Unity's physics timestep and disabling substepping would result in the same behavior, at much lower performance (as collision detection would be fully performed every timestep).
Reply
#3
Thank you so much for all the information Jose. With what you said I was able to get my drone hovering perfectly again by moving my FixedUpdate logic into a callback handler for ObiSolver.OnSubstep.

However I noticed one thing when doing this, it seems to break Rigidbody interpolation. That is, my drone has a Unity Rigidbody with interpolation enabled, and normally the drone's motion looks very smooth. But when I'm using the ObiSolver and responding to OnSubstep events, the apparent motion of the drone becomes very discrete, as though rigidbody interpolation is no longer enabled. This is especially noticeable in my game because I have a mechanic whereby the game enters slow motion (1/100th of realtime), and you can very clearly see the drone jumping around in space every time the updater calls Physics.Simulate().

Is this a known issue with Unity physics substepping in Obi? Is there a normal workaround for it to get smooth motion again?

Here's a video of what I'm talking about. In the first half of the video, I have substepping Unity physics enabled and you can clearly see the lack of interpolation. In the second half of the video, I disable it and you can see the normal, smooth motion of my rigidbody. (I'm also disabling a custom component I made which notifies my other scripts that Unity physics substepping is happening so they will switch from processing inside FixedUpdate() to OnSubstep)

Reply
#4
(01-07-2020, 03:09 AM)protomenace Wrote: Thank you so much for all the information Jose. With what you said I was able to get my drone hovering perfectly again by moving my FixedUpdate logic into a callback handler for ObiSolver.OnSubstep.

However I noticed one thing when doing this, it seems to break Rigidbody interpolation. That is, my drone has a Unity Rigidbody with interpolation enabled, and normally the drone's motion looks very smooth. But when I'm using the ObiSolver and responding to OnSubstep events, the apparent motion of the drone becomes very discrete, as though rigidbody interpolation is no longer enabled. This is especially noticeable in my game because I have a mechanic whereby the game enters slow motion (1/100th of realtime), and you can very clearly see the drone jumping around in space every time the updater calls Physics.Simulate().

Is this a known issue with Unity physics substepping in Obi? Is there a normal workaround for it to get smooth motion again?

Here's a video of what I'm talking about. In the first half of the video, I have substepping Unity physics enabled and you can clearly see the lack of interpolation. In the second half of the video, I disable it and you can see the normal, smooth motion of my rigidbody. (I'm also disabling a custom component I made which notifies my other scripts that Unity physics substepping is happening so they will switch from processing inside FixedUpdate() to OnSubstep)


Hi there!

This looks like a bug/overlook in Unity, I'd expect interpolation to happen in LateUpdate() after all physics calls for the frame have been done. This is what we do in Obi, and what is usually done in all physics engines. Interpolation works by:

- Storing the physics state at the end of the previous frame.
- Storing the physics state at the end of the current frame.
- Interpolate and render a state between both, using the difference between frame time and simulated time. So if you've only simulated 50% of the frame time, the rendered state would be a 50/50 blend of the past and the current physics states.

This can be done regardless of where/when you update the simulation since all you care is the state at the end of each frame, so I see no reason for manual updating to break interpolation. Will test it and get back to you asap.
Reply
#5
(01-07-2020, 07:57 AM)josemendez Wrote: Will test it and get back to you asap.

Were you ever able to get a chance to test this Jose?
Reply