Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice

Question How do I _really_ disable physics on a gameobject?

Discussion in 'Physics' started by sasq64, Feb 4, 2024.

  1. sasq64

    sasq64

    Joined:
    Jan 28, 2018
    Posts:
    13
    I want to disable physics completely on a gameobject and make it not be affected by other rigid bodies.

    Specifically, I want them disabled while in a moving drawer, so that they move with the drawer.
    So the game objects are children of the drawer, and I want them to move with the drawer like they would if no physics were involved.

    `isKinematic` does not work here, the objects then tend to stand still while the drawer animates below them.
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,506
    Just remove the Rigidbody component on those objects. You may re-add the Rigidbody component if you need them to react to physics again.

    From scripting, you may use
    Destroy(GetComponent<Rigidbody>())
    to remove the component from a GameObject, and
    gameObject.AddComponent<Rigidbody>()
    to re-add it. You need to configure it, as it's added with the default settings.
     
    codebiscuits likes this.
  3. sasq64

    sasq64

    Joined:
    Jan 28, 2018
    Posts:
    13
    But the rigidbody does have settings that needs to be saved, and I also normally have other components that depend on the RigidBody (at least XRBasInteractable since these are XR interactables) in which case I need to serialize and deserialize all of them which gets messy.

    I did notice however, that if you set `rigidBody.interpolate = RigidbodyInterpolation.None;` the objects do not move. Do you happen to know if this is defined behavior?
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,506
    Unfortunately that's the only way to completely disable physics in a GameObject. I don't know about XR interactables, but I'd double-check if/how such interactions could work with colliders alone, as those may still be active in a GameObject without rigidbody.

    Alternatively, in your case, you may leave physics enabled but configure the physics materials to a friction high enough so they keep static on the moving drawer. This would work as long as the drawer doesn't move abruptly and either 1) it's a non-kinematic rigidbody affected by regular physics in a standard way, or 2) it's a kinematic rigidbody moved exclusively with MovePosition and MoveRotation from FixedUpdate.

    No, that doesn't make much sense. There must be something else kicking in to cause such apparent behavior.
     
    codebiscuits likes this.
  5. codebiscuits

    codebiscuits

    Joined:
    Jun 16, 2020
    Posts:
    89
    Can you make it kinematic and add a custom script component to it to make it follow the drawer using Rigidbody.MovePosition from FixedUpdate?

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class FollowTransform : MonoBehaviour //So don't use parent/child, use this instead
    4. {
    5.     Rigidbody rb;
    6.     GameObject _followTransform;
    7.     Vector3 _offsetToTransform;
    8.     Quaternion _startingRotationToTransform;
    9.     public void Follow( GameObject followTransform ) { //I can't decide if this needs to be called from FixedUpdate so it picks up the correct offset synched to physics
    10.         rb = GetComponent<Rigidbody>();
    11.         _followTransform = followTransform;
    12.         _offsetToTransform = transform.position - _followTransform.transform.position;
    13.         _startingRotationToTransform = _followTransform.transform.rotation;
    14.         rb.isKinematic = true;
    15.         //Maybe you need to disable colliders in here too?
    16.     }
    17.     public void UnFollow(  ) {
    18.         _followTransform = null;
    19.         _offsetToTransform = Vector3.zero;
    20.         _startingRotationToTransform = Quaternion.identity;
    21.         if (rb != null)
    22.             rb.isKinematic = false;
    23.     }
    24.     void FixedUpdate()
    25.     {
    26.         if ( _followTransform != null ) {
    27.             //My quaternion maths is not too strong, this works rn in my tiny test, but I'm not certain of it:)
    28.             var rotatedOffset = _followTransform.transform.rotation * Quaternion.Inverse( _startingRotationToTransform ) * _offsetToTransform;
    29.             rb.MovePosition( _followTransform.transform.position + rotatedOffset );
    30.         }
    31.     }
    32. }
    33.  
     
    Edy likes this.
  6. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,913
    There's a chance that the changes made to the transform as a result of its parent (the drawer) moving around are not applied to the rigidbody, since rigidbody.position and transform.position are two different values.

    The reason for this is that rigidbodies do not update every frame (they update during FixedUpdate()) so when using rigidbody interpolation/extrapolation, transform.position is calculated by interpolating/extrapolating rigidbody.position over time, this avoids stuttering.

    Try using Physics.SyncTransforms. This will ensure rigidbody.position is set to the same values as transform.position.