How do I _really_ disable physics on a gameobject?

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.

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.

1 Like

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?

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.

1 Like

Can you make it kinematic and add a custom script component to it to make it follow the drawer using Rigidbody.MovePosition from FixedUpdate?

using UnityEngine;

public class FollowTransform : MonoBehaviour //So don't use parent/child, use this instead
{
    Rigidbody rb;
    GameObject _followTransform;
    Vector3 _offsetToTransform;
    Quaternion _startingRotationToTransform;
    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
        rb = GetComponent<Rigidbody>();
        _followTransform = followTransform;
        _offsetToTransform = transform.position - _followTransform.transform.position;
        _startingRotationToTransform = _followTransform.transform.rotation;
        rb.isKinematic = true;
        //Maybe you need to disable colliders in here too?
    }
    public void UnFollow(  ) {
        _followTransform = null;
        _offsetToTransform = Vector3.zero;
        _startingRotationToTransform = Quaternion.identity;
        if (rb != null)
            rb.isKinematic = false;
    }
    void FixedUpdate()
    {
        if ( _followTransform != null ) {
            //My quaternion maths is not too strong, this works rn in my tiny test, but I'm not certain of it:)
            var rotatedOffset = _followTransform.transform.rotation * Quaternion.Inverse( _startingRotationToTransform ) * _offsetToTransform;
            rb.MovePosition( _followTransform.transform.position + rotatedOffset );
        }
    }
}
1 Like

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.