Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Getting actors from bodyA and bodyB in Obi 6.0?
#1
Hi!

I've updated to Obi 6.0 and replaced contact.particle with contact.bodyA and contact.other with contact.bodyB, but when I collide 2 actors now, after the first collision or so none of the contacts are the 2 actors involved in the contact; most are null. 

Code:
public void OnSoftParticleCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
{
    foreach(var contact in e.contacts)
    {
        if(contact.distance<0.01f)
        {
            var thisActor = m_solver.particleToActor[contact.bodyA]; // often null
            var otherActor = m_solver.particleToActor[contact.bodyB]; // often null
            ...

world.colliderHandles doesn't seem to be right either. I was wondering, what is the correct way to get the 2 actors involved in a softbody/softbody collision now?

Thanks!

Matt
Reply
#2
They're retrieved exactly the same way. Tried to reproduce this behavior you mention, but for me all contacts have non-null entries in particleToActor. The colliderHandles array and the way it's managed hasn't changed at all, either.

There's some differences in the way you access contact data for surface collisions, but this only affects ropes and cloth, not softbodies.

Can you share the full script you're using so that I can take a look?

Thanks!
Reply
#3
Ah, I think it's because I'm disabling and enabling softbody components. I have expensive softbodies in my scene that slow the game down even when not in contact with any other softbodies, so I disable their softbody component until another one is near, enable it, then disable it again when nothing is in range again. It seems that the contacts report fine the first time, but after disabling the softbody and reenabling it, contacts are now null.

Repro:

1. Add my script to any game object in the Ball Pool Scene and inject the solver parameter.
2. Run Ball Pool Scene.
3. Drop 2 balls in the scene in contact, output window will say something like "Num contacts: Total = 78 Close: 17 Both Valid: 17". All good!
4 Disable and enable an Obi Softbody component on one of the balls in the editor by unchecking it and checking it again.
5. Output will now look like: "Num contacts: Total = 25 Close: 8 Both Valid: 0". "0" at the end with non-zero close contacts means both actors are null incorrectly.

My method of enabling/disabling softbody components worked in Obi 5.x but maybe I shouldn't be doing this and there's a better way now? Having softbodies active when not in contact and static does seem to have a big performance cost so I do need some solution for it.

As always, thoughts and suggestions most welcome and I'll happily help any way I can!

Code:
using UnityEngine;

public class TestParticleCollisions : MonoBehaviour
{
    public Obi.ObiSolver m_solver;

    void OnEnable()
    {
        m_solver.OnParticleCollision += OnSoftParticleCollision;
    }

    void OnDisable()
    {
        m_solver.OnParticleCollision -= OnSoftParticleCollision;
    }
    
    public void OnSoftParticleCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
    {
        if(e.contacts.Count>0)
        {
            int numCloseContacts = 0;
            int bothActorsNotNull = 0;

            foreach(var contact in e.contacts)
            {
                if(contact.distance<0.01f)
                {
                    var otherActor = m_solver.particleToActor[contact.bodyB];
            var thisActor = m_solver.particleToActor[contact.bodyA];

                    numCloseContacts++;

                    if( otherActor != null && thisActor != null )
                    {
                        bothActorsNotNull ++;
                    }
                }
            }

            string results = "Num contacts: Total = " + e.contacts.Count;
            results += " Close: " + numCloseContacts;
            results += " Both Valid: " + bothActorsNotNull;

            Debug.Log( results );
        }
    }
}


.cs   TestParticleCollisions.cs (Size: 1.29 KB / Downloads: 5)

Reply
#4
Hi Matt,

There's a couple things at play in this:

- There seems to be a bug in ObiSolver, introduced in 6.0 (thanks a bunch for reporting this!!), that causes entries in the particlesInActor array to be incorrectly flagged as "occupied" when disabling an actor. I still have to analyze it greater detail, but as far as I could reason it seems the culprit is a missing call in the solver's RemoveActor() method. Line 1145 should be:

Code:
FreeParticles(actor.solverIndices);

So the entire method looks like this:

Code:
public bool RemoveActor(ObiActor actor)
        {

            if (actor == null)
                return false;

            // Find actor index in our actors array:
            int index = actors.IndexOf(actor);

            // If we are in charge of this actor indeed, perform all steps necessary to release it.
            if (index >= 0)
            {
                actor.UnloadBlueprint(this);

                for (int i = 0; i < actor.solverIndices.Length; ++i)
                    particleToActor[actor.solverIndices[i]] = null;

                FreeParticles(actor.solverIndices);//<----ADD THIS LINE

                actors.RemoveAt(index);

                actor.solverIndices = null;

                // If this was the last actor in the solver, tear it down:
                if (actors.Count == 0)
                    Teardown();

                return true;
            }

            return false;
        }
You can try this yourself, the entries in particleInActor should no longer be null. A patch will be available by monday.

- The BallPool test scene contains a spawner object that sets the phase of the balls after spawning them. However, when an actor is enabled it copies all its data from the blueprint, except for positions and velocities . This means the ball's phase will revert to the one set in the blueprint if you manually deactivate/reactivate it. This will cause the ball to no longer collide with other actors sharing the same phase. This is the default behavior since Obi 4.X, so it should work the same way in 5.X and 6.X too.

For instance if you spawn a second ball in the scene, deactivate it and reactivate it, its phase will revert to 0. Now both have the same phase and won't collide with each other.

Let me know how it goes,
Reply
#5
Considering my repro was a bit misleading, you did well to figure out what my issue is!

I added the FreeParticles call to RemoveActor as you suggested. Unfortunately it will still break eventually with m_solver.particleToActor[contact.bodyA] starting to return null after a number of disable/enables, possibly less frequently but that's anecdotal. Sometimes it survives more and 10 enable/disables of multiple softbodies, sometimes it starts returning null actors after just a couple of enable/disable cycles. It could of course be something completely different, my repro is not as good any more. 

Happy to gather any info for you if it'd be helpful. I'm upgrading from the previous version of Obi, and the only changes I made were particle=>bodyA and other=>bodyB (and using pointA and pointB instead of point).
Reply
#6
Hi Matt,

My bad: there is a difference when accessing particle indices from contacts: now that simplices are a part of the engine and particles are just one simplex type, you should use the solver.simplices array, as contact.bodyA and contact.bodyB are simplex indices, not particle indices.

So instead of:

Code:
solver.particleToActor[contact.bodyA];

you should use:

Code:
solver.particleToActor[solver.simplices[contact.bodyA]];

Notice the extra indirection level: contact.bodyA is an index in the simplices array, and solver.simplices[contact.bodyA] is a particle index.

This wasn't mentioned in the changelog and is undocumented in the manual, so it's entirely my fault. Will update both the changelog and the manual asap.

Let me know how it goes,
Reply
#7
Dedo arriba 
Hi Jose,

I've just changed the code to your suggested fix and can confirm that it does indeed fully work now Sonrisa So that's me fully moved over to Obi 6 with only improvements and no issues, thank you!

Matt
Reply