Search Unity

Setting Rigidbody.isKinematic = true, colliders not working anymore

Discussion in '2D' started by modernator24, Feb 13, 2020.

  1. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    205
    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:
    Code (CSharp):
    1.  
    2.     using UnityEngine;
    3.     using UnityEngine.Experimental.U2D.IK;
    4.    
    5.     public class RagdollController : MonoBehaviour {
    6.         [SerializeField] private IKManager2D m_IKManager;
    7.         [SerializeField] private Transform[] m_RagdollTransforms;
    8.         private Rigidbody2D[] m_Rigidbodies;
    9.         private HingeJoint2D[] m_Joints;
    10.    
    11.         void Setup() {
    12.             m_Rigidbodies = new Rigidbody2D[m_RagdollTransforms.Length];
    13.             m_Joints = new HingeJoint2D[m_RagdollTransforms.Length];
    14.    
    15.             for (int i = 0; i < m_RagdollTransforms.Length; i++) {
    16.                 m_Rigidbodies[i] = m_RagdollTransforms[i].GetComponent<Rigidbody2D>();
    17.                 m_Joints[i] = m_RagdollTransforms[i].GetComponent<HingeJoint2D>();
    18.             }
    19.         }
    20.    
    21.         public void Enable() {
    22.             if (m_Rigidbodies == null) {
    23.                 Setup();
    24.             }
    25.    
    26.             m_IKManager.enabled = false;
    27.    
    28.             foreach (Rigidbody2D rbody in m_Rigidbodies) {
    29.                 rbody.isKinematic = false;
    30.                 rbody.gravityScale = 1.0f;
    31.             }
    32.    
    33.             foreach (HingeJoint2D joint in m_Joints) {
    34.                 joint.enabled = true;
    35.             }
    36.         }
    37.    
    38.         public void Disable() {
    39.             if (m_Rigidbodies == null) {
    40.                 Setup();
    41.             }
    42.    
    43.             m_IKManager.enabled = true;
    44.    
    45.             foreach (Rigidbody2D rbody in m_Rigidbodies) {
    46.                 rbody.isKinematic = true;
    47.                 rbody.gravityScale = 0.0f;
    48.             }
    49.    
    50.             foreach (HingeJoint2D joint in m_Joints) {
    51.                 joint.enabled = false;
    52.             }
    53.         }
    54.     }
    55.  
    Important part is method named Disable:

    Code (CSharp):
    1.  
    2.     public void Disable() {
    3.         if (m_Rigidbodies == null) {
    4.             Setup();
    5.         }
    6.  
    7.         m_IKManager.enabled = true;
    8.  
    9.         foreach (Rigidbody2D rbody in m_Rigidbodies) {
    10.             rbody.isKinematic = true;
    11.             rbody.gravityScale = 0.0f;
    12.         }
    13.  
    14.         foreach (HingeJoint2D joint in m_Joints) {
    15.             joint.enabled = false;
    16.         }
    17.     }
    18.  
    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:

    Code (csharp):
    1.  
    2.     [Enemy] - Rigidbody2D and Scripts that controlling character
    3.        └ [Mesh] - IKManager2D
    4.            └ [Body] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
    5.            └ [Head] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
    6.            └ [LeftArm] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
    7.            └ [RightArm] - SpriteRenderer/SpriteSkinEntity/SpriteSkin
    8.            └ [Root]
    9.                 └ [Stomach] - From here, every child has Collider2D/Rigidbody2D/HingeJoint2D
    10.                      └ [Chest]
    11.                           └ [Head]
    12.                           └ [UpperArmL]
    13.                                  └ [LowerArmL]
    14.                           └ [UpperArmR]
    15.                                  └ [LowerArmR]
    16.                      └ [UpperLegL]
    17.                             └ [LowerLegL]
    18.                      └ [UpperLegR]
    19.                             └ [LowerLegR]
    20.  
    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 Package@2.1.0, 2D IK Package@1.1.0.
     
  2. VgReborn_2

    VgReborn_2

    Joined:
    Apr 17, 2020
    Posts:
    4
    Sorry for late response and maybe you know the answer now but whenever you set a rigidbody to kinematic, it will make it ignore every Unity physical engine, in which it makes it ignore collisions all together. If you still want it to work, I suggest going to rigidbody, collision detection, and change it discrete to Continuous Speculative. I hope this helps
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    This isn't that accurate TBH. Kinematic bodies don't react to forces and don't have a collision response but they can detect and report collisions if you want them to. Also, any Dynamic body and its colliders will still contact it so it's not ignored by the physics engine.

    Also, "Continuous Speculative" is 3D so I think you're getting a little confused here.