Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  (Solved)When a rigidbody with a rope attached is deleted, the rope attaches elsewhere
#1
Dedo arriba 
I've encountered an issue with pin constraints that even occurs in the demo samples provided with the asset:

When a rigidbody with a rope attached (via a pin constraint) is deleted, the rope will suddenly attach to another rigidbody in the scene.

I'm assumed originally that when one actor is deleted, any constraints between them would automatically get deleted as well. This appears to not be the case. Not to matter, it seems relatively simple to fix this: shove some code that destroys the ObiParticleAttachment script when the m_Target it points to gets destroyed.

I'm just wondering what you'd recommend to be the best way to handle this. Some ideas I had and the concerns involved with each:

  • When the attachment gets created, add a simple script with OnDisable() handler that calls a delegate. Add a new method - OnTargetDisabled() - to the delegate, which is called when m_Target is disabled. 
    Concern: While simple, it seems unnecessary and incomplete. Given that an ObiCollider is needed to make a dynamic attachment, and the ObiCollider likely already handles its own destruction or deactivation, this could be a more elegant place to handle ALL relationships between the ObiCollider and other entities.
  • Add code into the OnDestroy/OnDisable/OnEnable callbacks of ObiCollider (and/or ObiRigidbody) that ensure that upon its destruction or deactivation, relationships with other entities (be that via pin constraints, ObiParticleAttachment, or whatever other relationships I'm currently unaware of) are severed or suspended appropriately.
    Concern: Modifying unfamiliar code is always a bit risky. Plus, I'm not sure where Obi keeps track of all the relevant relationships, whether they're enumerable, or if they're stored in a way where it'd be quick and painless to find them given a ObiCollider/ObiRigidbody. Besides, ObiParticleAttachment might not be informed that the constraint it generated was removed and misbehave, and extra handling would need to take place there anyway.
  • I broke something and this is entirely my fault.
    Concern: After reviewing the diffs between the latest version of unmodified Obi and the version I'm using with my changes included, there does not appear to be any changes that would interfere with how the demo scenes work.
If I can get this working, I'd be happy to submit the code changes for inclusion in future versions. I'd imagine objects being destroyed when they have ropes attached might not be a rare occurrence in some games, and they'd likely benefit from this happening under the hood.

Thanks!  Gran sonrisa
Reply
#2
Hi there,

Thanks for reporting this! On paper, ObiParticleAttachments are already handling the case where targets become inactive or are destroyed. This is done in the UpdateAttachment method of ObiParticleAttachment.cs, which is called at the start of every step to check if there's been changes that would require updating constraints. This avoids having to explicitly keep track of all attachments that may affect any given collider.

However there's a bug (I believe a regression from 5.X) that overlooks the case where the target is destroyed instead of deactivated: the isBound variable returns false -since there's no longer any target to be bound to- and the pin constraints are not flagged dirty. Just add this else clause at the very end of the method:

Code:
else if (!isBound && attachedColliderHandleIndex >= 0)
{
     attachedColliderHandleIndex = -1;
     m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
}

Once integrated in the method, it should look like this:

Code:
if (enabled && m_Actor.isLoaded && isBound)
{
//....
// all existing code for static/dynamic attachments here
//....
}
else if (!isBound && attachedColliderHandleIndex >= 0) //<--new code
{
     attachedColliderHandleIndex = -1;
     m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
}

Let me know how it goes, don't hesitate to get back in touch if you need any help. cheers!
Reply
#3
(12-07-2022, 07:35 AM)josemendez Wrote:
Code:
if (enabled && m_Actor.isLoaded && isBound)
{
//....
// all existing code for static/dynamic attachments here
//....
}
else if (!isBound && attachedColliderHandleIndex >= 0) //<--new code
{
     attachedColliderHandleIndex = -1;
     m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
}

Works perfectly. Much less code than the stuff I put in. Thanks! Gran sonrisa
Reply