Exclude layers from Ragdoll ability

Cheo

Active member
Hello everyone, here is one more addition which I think deserves to be in UCC by default. The Ragdoll ability looks for rigidbodies in the whole character's hierarchy and stores them in a list, but the thing is not all rigidbodies may be limbs - one clear example I've recently struggled with is the Trigger Sensor object from Sensor Toolkit, which has a mesh collider and rigidbody attached to it. It's an object that needs to constantly remain on a specific Sensor layer, or it creates some unwanted collision issues.

So in order to fix that, I recommend making your own Ragdoll script that will inherit from the original one :

C#:
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Character.Abilities;
using UnityEngine;

public class MyRagdoll : Ragdoll
{

    [SerializeField] protected LayerMask m_ExcludedLayers;
    public LayerMask ExcludedLayers { get { return m_ExcludedLayers; } set { m_ExcludedLayers = value; } }

    public override void Awake()
    {
        var characterRigidbody = m_GameObject.GetCachedComponent<Rigidbody>();
        var rigidbodies = m_GameObject.GetComponentsInChildren<Rigidbody>();

        int lengthMod = 1;

        foreach (Rigidbody r in rigidbodies)
        {
            if ((m_ExcludedLayers.value & (1 << r.gameObject.layer)) > 0)
            {
                lengthMod++;
                continue;
            }
        }

        // The character's Rigidbody should be ignored.
        var index = 0;
        m_Rigidbodies = new Rigidbody[rigidbodies.Length - lengthMod];
        m_RigidbodyGameObjects = new GameObject[m_Rigidbodies.Length];
        for (int i = 0; i < rigidbodies.Length; ++i)
        {
            if (rigidbodies[i] == characterRigidbody)
            {
                continue;
            }

            if ((m_ExcludedLayers.value & (1 << rigidbodies[i].gameObject.layer)) > 0)
            {
                continue;
            }

            m_Rigidbodies[index] = rigidbodies[i];
            m_RigidbodyGameObjects[index] = rigidbodies[i].gameObject;
            index++;
        }

        EventHandler.RegisterEvent<Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath);
        EventHandler.RegisterEvent(m_GameObject, "OnWillRespawn", OnRespawn);

        EnableRagdoll(false, Vector3.zero, Vector3.zero);
    }

}

I'm not sure the way I calculated the array's size is the best one, but it works ! With this done, just remove the existing Ragdoll ability if there's one on your character, add your custom one, set the layers you want to be excluded, and you should be good to go !

Let me know if you find this useful and whether it works correctly on your end.

Edit : forgot to mention that you might need to set these values in Ragdoll to public in order for them to be accessible from your custom script :

C#:
        public Rigidbody[] m_Rigidbodies;
        public GameObject[] m_RigidbodyGameObjects;
 
Top