I have a rigged 2D character and used Collider2D/Rigidbody2D/HingeJoint2D to body parts to implement ragdoll.
It works fine, but I needed to run ragdoll physics only when character is dead. So I made a script to easily control ragdoll related features called RagdollController:
using UnityEngine;
using UnityEngine.Experimental.U2D.IK;
public class RagdollController : MonoBehaviour {
[SerializeField] private IKManager2D m_IKManager;
[SerializeField] private Transform[] m_RagdollTransforms;
private Rigidbody2D[] m_Rigidbodies;
private HingeJoint2D[] m_Joints;
void Setup() {
m_Rigidbodies = new Rigidbody2D[m_RagdollTransforms.Length];
m_Joints = new HingeJoint2D[m_RagdollTransforms.Length];
for (int i = 0; i < m_RagdollTransforms.Length; i++) {
m_Rigidbodies[i] = m_RagdollTransforms[i].GetComponent<Rigidbody2D>();
m_Joints[i] = m_RagdollTransforms[i].GetComponent<HingeJoint2D>();
}
}
public void Enable() {
if (m_Rigidbodies == null) {
Setup();
}
m_IKManager.enabled = false;
foreach (Rigidbody2D rbody in m_Rigidbodies) {
rbody.isKinematic = false;
rbody.gravityScale = 1.0f;
}
foreach (HingeJoint2D joint in m_Joints) {
joint.enabled = true;
}
}
public void Disable() {
if (m_Rigidbodies == null) {
Setup();
}
m_IKManager.enabled = true;
foreach (Rigidbody2D rbody in m_Rigidbodies) {
rbody.isKinematic = true;
rbody.gravityScale = 0.0f;
}
foreach (HingeJoint2D joint in m_Joints) {
joint.enabled = false;
}
}
}
Important part is method named Disable:
public void Disable() {
if (m_Rigidbodies == null) {
Setup();
}
m_IKManager.enabled = true;
foreach (Rigidbody2D rbody in m_Rigidbodies) {
rbody.isKinematic = true;
rbody.gravityScale = 0.0f;
}
foreach (HingeJoint2D joint in m_Joints) {
joint.enabled = false;
}
}
Method "Disasble" iterate internal rigidbodies and joints, and set isKinematic to true to prevent physics working, also turn off each hinge joint to prevent any joint physics.
However when I run the game and call Disable(), character just falling through the ground. Note that structure of character looks like this:
[Enemy] - Rigidbody2D and Scripts that controlling character
└ [Mesh] - IKManager2D
└ [Body] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
└ [Head] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
└ [LeftArm] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
└ [RightArm] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
└ [Root]
└ [Stomach] - From here, every child has Collider2D/Rigidbody2D/HingeJoint2D
└ [Chest]
└ [Head]
└ [UpperArmL]
└ [LowerArmL]
└ [UpperArmR]
└ [LowerArmR]
└ [UpperLegL]
└ [LowerLegL]
└ [UpperLegR]
└ [LowerLegR]
Root of Enemy GameObject doesn't have collider, instead legs have it so by default character can stand on the ground.
However when I set rigidbody.isKinematic = true, colliders inside of legs and all other bones just not working and character just falling through.
I have no idea why disabling rigidbody affects to collider. I can temporarily fixed by adding simple box collider 2d near by character's foot and only activate it when character is still alive(means that deactivate when character is dead).
This way my character not falling through the ground so you might think the problem was solved, but there is huge problem, because unless set isKinematic = false, Raycast2D does not hitanything(It only hit the collider I just added to prevent falling through the ground, totally useless).
I want to keep my colliders in each body parts: head/stomach/chest/arms/legs to precise hit detection(I was used single capsule collider but hit detection was horrible). Am I doing wrong way, or is this glitch?
How do I make my colliders work even Rigidbody2D is turned off? Using Unity 2019.1.0f2 and 2D Animation [email protected], 2D IK [email protected].