Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Obi 7 disable simulation
#1
Hi, in Obi6 I could disable simulation, but still have rendering done by not running code in custom Updater. How would I do this in new version?

This was my updater before:

Code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using Obi;
/// <summary>
/// Updater class that will perform simulation during FixedUpdate(). This is the most physically correct updater,
/// and the one to be used in most cases. Also allows to perform substepping, greatly improving convergence.

//[AddComponentMenu("Physics/Obi/Obi Fixed Updater", 801)]
[ExecuteInEditMode]
public class CustomUpdater : ObiUpdater
{
    /// <summary>
    /// Each FixedUpdate() call will be divided into several substeps. Performing more substeps will greatly improve the accuracy/convergence speed of the simulation.
    /// Increasing the amount of substeps is more effective than increasing the amount of constraint iterations.
    /// </summary>
    [Tooltip("Amount of substeps performed per FixedUpdate. Increasing the amount of substeps greatly improves accuracy and convergence speed.")]
    public int substeps = 4;
    public bool solve = false;

    private float accumulatedTime;

    private void OnValidate()
    {
        substeps = Mathf.Max(1, substeps);
    }

    private void Awake()
    {
        accumulatedTime = 0;
    }

    private void OnDisable()
    {
        //Physics.autoSimulation = true;
    }

    private void FixedUpdate()
    {
        if (solve)
        {
            ObiProfiler.EnableProfiler();

            BeginStep(Time.fixedDeltaTime);

            float substepDelta = Time.fixedDeltaTime / (float)substeps;

            // Divide the step into multiple smaller substeps:
            for (int i = 0; i < substeps; ++i)
                Substep(Time.fixedDeltaTime, substepDelta, substeps - i);

            EndStep(substepDelta);

            ObiProfiler.DisableProfiler();

            accumulatedTime -= Time.fixedDeltaTime;
        }
    }

    private void Update()
    {
        ObiProfiler.EnableProfiler();
        Interpolate(Time.fixedDeltaTime, accumulatedTime);
        ObiProfiler.DisableProfiler();

        if (solve)
            accumulatedTime += Time.deltaTime;
    }
}
Reply
#2
Hi,

You can set the solver's maxStepsPerFrame to zero. This will disable simulation entirely, but keep rendering on.

kind regards,
Reply
#3
(27-03-2025, 01:08 PM)positionsjosemendez Wrote: Hi,

You can set the solver's maxStepsPerFrame to zero. This will disable simulation entirely, but keep rendering on.

kind regards,

Thank you. Will it still update the rendering if I am setting particle positions in code?
Reply
#4
(27-03-2025, 01:32 PM)natko1412 Wrote: Thank you. Will it still update the rendering if I am setting particle positions in code?

Yes, since they won't be overwritten by the simulation.
Reply
#5
(27-03-2025, 01:45 PM)josemendez Wrote: Yes, since they won't be overwritten by the simulation.

I am using Compute backend.

In my server app, the simulation is running and everything is fine. On my client, I am setting the positions and velocities like this:


Code:
for (int i = 0; i < positions.Count; ++i)
        {
            int solverIndex = actor.solverIndices[i];
            actor.solver.positions[solverIndex] = positions[i];
            actor.solver.velocities[solverIndex] = velocities[i];
.
.
.
where positions and velocities are synchronized lists. This worked very well in Obi 6, but now it doesn't work no matter what. Can you tell me if something else changed. It seems from documentation like positions and velocities are automatically synced to GPU so I don't know what I'm missing.
Reply
#6
(27-03-2025, 05:49 PM)natko1412 Wrote: I am using Compute backend.

In my server app, the simulation is running and everything is fine. On my client, I am setting the positions and velocities like this:


Code:
for (int i = 0; i < positions.Count; ++i)
        {
            int solverIndex = actor.solverIndices[i];
            actor.solver.positions[solverIndex] = positions[i];
            actor.solver.velocities[solverIndex] = velocities[i];
.
.
.
where positions and velocities are synchronized lists. This worked very well in Obi 6, but now it doesn't work no matter what. Can you tell me if something else changed. It seems from documentation like positions and velocities are automatically synced to GPU so I don't know what I'm missing.

Hi!

Positions and velocities are read back from the GPU at the end of each simulation step, and uploaded to the GPU at the start of the next step as per the manual:

Quote:Obi will automatically upload particle data to the GPU at the start of every simulation step (only those data lists that have been modified by the CPU since the last time they were uploaded).

You’ve disabled simulation by setting the maximum amount of steps per frame to zero, so they won’t be automatically sent to the GPU. You must send them manually. Call the Upload() method on both the positions and velocities solver arrays after your for loop to do so.

Kind regards,
Reply
#7
Thank you, that makes sense!


Now I'm still struggling to get it working. I think the problem might be in changing length of the rope. I am sending the changes and calling cursor.ChangeLength(deltaLen) on the client side, but it seems nothing happens. I suppose it is the same thing as in documentation it says that the length is changed at next solver update.

What could be the workaround? Maybe to manually activate particles as they get activated on the server side ?
Reply