08-05-2026, 08:50 AM
(This post was last modified: 08-05-2026, 09:09 AM by josemendez.)
(07-05-2026, 07:29 PM)Jawsarn Wrote: It is my understanding that it should, see image of profiler for player steps.
Interpolation will of course still work, and physics state (positions/rotations) will still be interpolated from the last two physics updates when rendering a frame during which physics haven't been updated at all.
However since the timestep value is the same for both engines, Obi will read rigidbody positions/orientations during frames where a rigidbody physics update is guaranteed to have taken place. As a result, interpolated and fixed values will be the same.
(07-05-2026, 07:29 PM)Jawsarn Wrote: I think it slightly improves it, but it does not remove the jittery impulses. (Enabling interpolation on solver does not improve it). See video.
https://drive.google.com/file/d/1UtywXEa...sp=sharing
I've asked you for permission to see the video, as soon as you accept my request I'll take a look.
Regarding manually updating the solver, all you need to do is disable the solver and then manually call StartSimulation(stepDelta, numSteps) and Render(accumulatedTime). Here's an example that advances the simulation 0.03 seconds every frame you press "space":
Code:
using UnityEngine;
using Obi;
[RequireComponent(typeof(ObiSolver))]
public class ManualSolverUpdate : MonoBehaviour
{
ObiSolver solver;
void Start()
{
solver = GetComponent<ObiSolver>();
solver.enabled = false;
}
void Update()
{
solver.Render(0);
if (Input.GetKey(KeyCode.Space))
{
solver.StartSimulation(0.01f, 1);
solver.StartSimulation(0.01f, 1);
solver.StartSimulation(0.01f, 1);
}
}
}Keep in mind that simulation is multithreaded: StartSimulation() merely kicks off the simulation and the main thread continues execution. Calling StartSimulation() again or calling Render() will force the main thread to wait for the current simulation in flight to finish before continuing.
Because of this, it's best to call Render() as late as possible in the frame: in fact, when using asynchronous mode it's called at the *start of the next frame* to allow as much time as possible to pass between StartSimulation() and Render() and minimize the chances of stalling the main thread. I'm doing the same in the example above, but calling Render() immediately after StartSimulation would be equally valid.
Also notice the second parameter of StartSimulation(), "numSteps". This basically enqueues multiple simulation steps without forcing the main thread to wait between them, so calling StartSimulation(0.01,3) is the same as calling StartSimulation(0.01,1) 3 times -except that the main thread isn't stalled in between steps. You can't always do this, but it's a handy thing to have if you want to coalesce multiple steps.
For reference, here's how you would implement a fixed time stepping scheme using the above methods:
Code:
using UnityEngine;
using Obi;
[RequireComponent(typeof(ObiSolver))]
public class ManualSolverUpdate : MonoBehaviour
{
ObiSolver solver;
public float fixedTimestep = 0.02f;
void Start()
{
solver = GetComponent<ObiSolver>();
solver.enabled = false;
}
float accumulator;
void Update()
{
accumulator += Time.deltaTime;
while (accumulator > 0)
{
accumulator -= fixedTimestep;
solver.StartSimulation(fixedTimestep, 1);
}
solver.Render(accumulator);
}
}This way of using the engine is undocumented, so let me know if you encounter any issues or have any questions.

