- Home /
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).
Oppositely, the collision works as I would expect when using the transform.localRotation approach (i.e. what I mean by 'expected physical interactions').
Question: How may I observe expected physical interactions while using Rigidbody.MoveRotation()?
Unsuccessful attempts at making this work:
changing the mass of the cube (keeps happening even with mass 1);
Making the platform kinematic and having the cube apply downward force (gave up as way too advanced for me at the moment);
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));
}
}
Answer by Edy · Jan 25, 2021 at 10:14 AM
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.
Edy, thank you so much for the crystal clear explanation. $$anonymous$$uch appreciated!!
You're welcome! I've amended the reply to include AddTorque and other related methods.
Your answer
Follow this Question
Related Questions
Camera and mesh not colliding 1 Answer
Object Flies into Air Upon Collision, or goes through hill depending on isKinematic settings 1 Answer
Rigidbody doesn't rotate after collision 3 Answers
Knock down moving target ridigbody from collision. 1 Answer
Rigidbody rotation constantly spins upon collision. 3 Answers