Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Obi fluid collision
#1
I have a container with liquid which I move, I want it to do something when it spills and collides with the floor, I am using an event to check when it collides with the floor, but the performance when using this script drops from 50 fps to 17fps what I could do ?

Code:
    void Awake()
    {
        solver = GetComponent<Obi.ObiSolver>();
    }
    
    void OnEnable()
    {
        solver.OnCollision += Solver_OnCollision;
    }

    void OnDisable()
    {
        solver.OnCollision -= Solver_OnCollision;
    }
    void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
    {
        var world = ObiColliderWorld.GetInstance();
        foreach (Oni.Contact contact in e.contacts)
        {
            // this one is an actual collision:
            if (contact.distance < 0.01)
            {
                ObiColliderBase collider = world.colliderHandles[contact.other].owner;
                if (collider.name!="Piso")
                {
                    Debug.Log(collider.name);
                    solver.OnCollision -= Solver_OnCollision;
                    // do something with the collider.
                }
            }
        }
    }
Reply
#2
(06-03-2021, 02:51 AM)JskT01 Wrote: I have a container with liquid which I move, I want it to do something when it spills and collides with the floor, I am using an event to check when it collides with the floor, but the performance when using this script drops from 50 fps to 17fps what I could do ?

Code:
void Awake()
{
solver = GetComponent<Obi.ObiSolver>();
}

void OnEnable()
{
solver.OnCollision += Solver_OnCollision;
}

void OnDisable()
{
solver.OnCollision -= Solver_OnCollision;
}
void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
{
var world = ObiColliderWorld.GetInstance();
foreach (Oni.Contact contact in e.contacts)
{
// this one is an actual collision:
if (contact.distance < 0.01)
{
ObiColliderBase collider = world.colliderHandles[contact.other].owner;
if (collider.name!="Piso")
{
Debug.Log(collider.name);
solver.OnCollision -= Solver_OnCollision;
// do something with the collider.
}
}
}
}

Remove the Debug.Log. Writing to the console is really slow, and your code does it once per contact, every frame.

Let me know if that improves it Sonrisa

Edit: didnt realize you’re unsubscribing from the collision event inside the contact loop, so the debug.log might not be the cause. also check how many times is FixedUpdate() being called per frame. You can easily see this in the profiler. If it’s more than once, you might be suffering from death spiralling (discussed often in this forum). Let me know how it goes.
Reply
#3
(06-03-2021, 09:41 AM)josemendez Wrote: Remove the Debug.Log. Writing to the console is really slow, and your code does it once per contact, every frame.

Let me know if that improves it Sonrisa

Edit: didnt realize you’re unsubscribing from the collision event inside the contact loop, so the debug.log might not be the cause. also check how many times is FixedUpdate() being called per frame. You can easily see this in the profiler. If it’s more than once, you might be suffering from death spiralling (discussed often in this forum). Let me know how it goes.
I already checked and fixed update is only called once, I think it happens because it is called by all the particles that make up my fluid even though it is not performing a function when it collides with the container it is detecting it and it is what generates the lowering of frames, is there a way that it doesn't detect collisions with the container? I need it to collide but the event is not fired with the container
Reply
#4
(06-03-2021, 09:51 PM)JskT01 Wrote: I already checked and fixed update is only called once, I think it happens because it is called by all the particles that make up my fluid even though it is not performing a function when it collides with the container it is detecting it and it is what generates the lowering of frames, is there a way that it doesn't detect collisions with the container? I need it to collide but the event is not fired with the container

The code, as it is written, should iterate through all particles once. As soon as it finds a collider that's not named "Piso", it will unsubscribe from the collision event and the script will do nothing from that point on.

Iterating trough all particles once is of course not enough to bring fps from 50 to 17, that's around 38 ms/frame which is a lot of time. If FixedUpdate() is only called once, then what's taking up all that time in the profiler? Did you see anything unusual in the profiler?
Reply
#5
(08-03-2021, 08:24 AM)josemendez Wrote: The code, as it is written, should iterate through all particles once. As soon as it finds a collider that's not named "Piso", it will unsubscribe from the collision event and the script will do nothing from that point on.

Iterating trough all particles once is of course not enough to bring fps from 50 to 17, that's around 38 ms/frame which is a lot of time. If FixedUpdate() is only called once, then what's taking up all that time in the profiler? Did you see anything unusual in the profiler?
I already saw my error when using VR the fixed time is updated when doing play to 0.0111 and it starts to call twice, but if I reduce maximium allowed timestep to 0.0111 so that it is called once, the animations and everything is altered, I can't find one practical solution
Reply
#6
(08-03-2021, 07:05 PM)JskT01 Wrote: I already saw my error when using VR the fixed time is updated when doing play to 0.0111 and it starts to call twice, but if I reduce maximium allowed timestep to 0.0111 so that it is called once, the animations and everything is altered, I can't find one practical solution

Reducing the maximum allowed timestep to the same value as the fixed timestep will only allow Unity to perform one physics step per frame, at most. This can result in slow-motion physics if your frames take longer than 11 ms to render.

There's no sure-fire way to fix this, except improving performance. Which takes us back to the original issue: there's no way iterating through all particles once per frame (what your script does) will take 38 ms/frame.

Can you share a screenshot of your profiler?
Reply
#7
(09-03-2021, 11:27 AM)josemendez Wrote: Reducing the maximum allowed timestep to the same value as the fixed timestep will only allow Unity to perform one physics step per frame, at most. This can result in slow-motion physics if your frames take longer than 11 ms to render.

There's no sure-fire way to fix this, except improving performance. Which takes us back to the original issue: there's no way iterating through all particles once per frame (what your script does) will take 38 ms/frame.

Can you share a screenshot of your profiler?
proffiler here is the capture
Reply
#8
(09-03-2021, 09:53 PM)JskT01 Wrote: proffiler here is the capture

BeginStep takes 15.8 ms, the collision callback is executed there so my guess is your code is indeed taking that much time. How many particles are there in your solver? how many contacts?
Reply
#9
(10-03-2021, 09:05 AM)joseméndez Wrote: BeginStep tarda 15,8 ms, la devolución de llamada de colisión se ejecuta allí, por lo que supongo que su código está tardando tanto tiempo. ¿Cuántas partículas hay en su solucionador? cuantos contactos?
There are 1500 particles in total for the fluid, plus I use obi rope in addition to obi fluid
Reply
#10
(10-03-2021, 07:55 PM)JskT01 Wrote: There are 1500 particles in total for the fluid, plus I use obi rope in addition to obi fluid

Hi there,

Are ropes and fluid in the same solver? the solver component should show statistics for total amount of particles and contacts in an info box at the top of the inspector.

Depending on how many particles are in contact with colliders, there can be several thousand contacts since there's typically more than one contact per particle, when the fluid is at rest. Iterating trough all of them in the main thread every frame can have an impact on performance.

If this is the case, I'd recommend:

- Iterating trough the contacts in parallel.
- Spread iteration over multiple frames, so that not every contact is checked every frame. You can instead iterate trough a fixed number of contacts per frame, until you have checked all of them, then update the contact list.
Reply