How may I observe expected physical interactions while using Rigidbody.MoveRotation()?

Greetings Developers!

I have a circular platform (built using a sphere with scale 10, -0.1, 10) of which I control the pitch (x) and roll (z) to balance a sphere on top of it.

@Eno-Khaon kindly provided the code below to make the platform move as I desire: limited rotation on both the x and z axes (frozen y axis), so that the platform cannot go beyond a discretionary tilt angle in any direction. Their suggestion is an improvement to my transform.localRotation approach (Click here to visit my previous question).

One challenge I intend to add to the ‘game’ are heavy, falling objects meant to destabilize the platform while balancing the ball. So, I created a HeavyCube (50 mass) and let it drop from a certain height. The issue is that with Rigidbody.MoveRotation(), the cube simply goes through the platform, and I just cannot understand why. My guess is that: between providing discrete rotations through Rigidbody.MoveRotation() and honoring physical interactions between the platform and the cube, the engine gives precedence to the former, causing this abrupt ‘fall-through-collider’ effect (fyi, the effect happens regardless of whether I am holding down any input key or not).
174797-moverotationcollision.gif

Oppositely, the collision works as I would expect when using the transform.localRotation approach (i.e. what I mean by ‘expected physical interactions’).
174798-localrotationcollision.gif

**Question: How may I observe expected physical interactions while using Rigidbody.MoveRotation()? **

Unsuccessful attempts at making this work:

  1. changing the mass of the cube (keeps happening even with mass 1);
  2. Making the platform kinematic and having the cube apply downward force (gave up as way too advanced for me at the moment);
  3. Introducing if-statements to apply Rigidbody.MoveRotation() only when collision with HeavyCube is not detected (closest I got to something acceptable, but still ugly and non-realistic).

Would also deeply appreciate an explanation as to what is causing the fall-through-collider effect.

Thanks in advance, and please let me know if I can provide any additional info to make the question clearer. Cheers!

public class TiltPlatform : MonoBehaviour
    {
        public float maxAngle; // The maximum angle of rotation allowed
        public float tiltSpeed; // Rotation speed, up to maxAngle
        public float returnSpeed; // Speed to return to original orientation
        Vector2 currentInput; // The current frame's input to apply to the total
        Vector2 totalInput; // The combined totals from rotation inputs
        private Rigidbody m_Rigidbody;
    
        private void Start()
        {
            m_Rigidbody = GetComponent<Rigidbody>();
        }
    
        // Update is called once per frame
        void Update()
        {
            currentInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
        }
    
        private void FixedUpdate()
        {
            // If no input is being provided, ease total input(s) toward 0
            if (Mathf.Approximately(currentInput.sqrMagnitude, 0.0f))
            {
                // Time.deltaTime is implicitly converted to Time.fixedDeltaTime
                // when called inside FixedUpdate()
                totalInput = Vector2.MoveTowards(totalInput, Vector2.zero, returnSpeed * Time.deltaTime);
            }
            else
            {
                // If there's input, apply it to the running total here
                totalInput += currentInput * Time.deltaTime * tiltSpeed;
                // If the total vector length exceeds the maximum, adjust it
                if (totalInput.sqrMagnitude > maxAngle * maxAngle)
                {
                    totalInput = totalInput.normalized * maxAngle;
                }
                // Note that this approach should move smoothly toward the current
                // input, while not aligning to cardinal directions easily. 
                // There are many ways to design this, so this is simply
                // one of many options available
            }
            // Now, regardless of how the totalInput has changed, the rotation can be
            // set at this point (add restrictions as desired)
    
            m_Rigidbody.MoveRotation(Quaternion.AngleAxis(totalInput.x, Vector3.forward) * Quaternion.AngleAxis(totalInput.y, Vector3.left));
        }
    }

Question: How may I observe expected physical interactions while using Rigidbody.MoveRotation()?

You can’t, unless you write your own collision solver. MovePosition/MoveRotation forcefully “teleport” the object to the new position/rotation in world coordinates. This causes physical effects in other rigidbodies but not in themselves.

Physical interactions require objects to be moved using Rigidbody.AddForce / AddTorque and related methods (AddForceAtPosition, AddRelativeTorque etc) exclusively. These allow the physics solver to compute and resolve the contacts and collisions. Note that the AddForce/AddTorque methods include options to change velocity, acceleration and momentum directly. For example, gravity is implemented by simply applying AddForce using the ForceMode.Acceleration option.

Otherwise, using MovePosition/MoveRotation, modifying the Transform or changing Rigidbody.velocity overrides the results from the physics solver typically causing inconsistent effects.