- Home /
How to stop MoveRotation when rigidbody is facing a specific euler angle
I have a cup which has some objects inside. I want to rotate the cup from a script so it lets the objects fall. I must use Rigidbody.MoveRotate to avoid the objects pass through the cup's mesh while it's moving. So default cup's rotation (euler) is (0,0,0) and it must rotate on both x and y axis to (135,70,0). The problem is how to know when the cup has reached the correct rotation so I can stop MoveRotation to keep rotating forever.
Here is my code:
void Update () {
Vector3 rota = new Vector3(135, 70, 0);
Quaternion rotationDelta = Quaternion.Euler(rota * Time.deltaTime);
Rigidbody rigid = GetComponent<Rigidbody>();
rigid.MoveRotation(rigid.rotation * rotationDelta);
}
I have tried to check:
if (Quaternion.Angle(transform.rotation, Quaternion.Euler(rota)) > angleThreshold)
But it won't work because in real time Euler angles of the object are so messed up by the quaternion rotation (because I'm rotating 2 axis at once and the rotation on 1 axis is actually moving the other axis as it's rotating and viceversa, that's why unity uses quaternions in the first place)
Any help?
Answer by maxoja · Sep 18, 2018 at 11:09 PM
The solution toward your problem is relatively similar to the answer from this question.
However, due to your rigidbody-related constraints, it needs some little modification and the code below should work.
public float speed = 1;
float ratio = 0;
Quaternion rotationA = Quaternion.Euler(0, 0, 0);
Quaternion rotationB = Quaternion.Euler(135, 70, 0);
public void Update()
{
ratio += Time.deltaTime;
ratio = Mahtf.Clamp(ratio, 0f, 1f);
rigid.MoveRotation(Quaternion.Lerp(rotationA, rotationB, ratio));
if ( ratio == 1 )
print("it is stopped now")
}
I wish this helps.
@maxoja after some testing I have realised the rotation is completed before ratio gets to 1, and I can't find why. I mean, the object finishes rotating in the right angle but at that time ratio is 0,3. As I need to inmediatly move the object after it finishes its rotation the result is a 0.7 seconds delay between rotation and movement :(
No offense, I am rather positive that ratio should be 1.0 when your object rotated to the target rotation. Let's figure this out together ;). First of all, I wonder where(which part of code) did you debug ratio and how did you check that your object should start moving.
in case anyone needs this. What @Baalhug said might be the case if you do modify rotationA as you rotate. This could be you using transform.rotation. What you need to do is store transform.rotation at the start of the rotation to rotationA. Then update it after the ratio reaches 1.
Answer by kevojo · Sep 19, 2018 at 05:08 AM
Just use vector3.angle
Transform AimTransform; //this object will hold the target rotation
AimTransform.Lookat(someTarget);
if (Vector3.angle(transform.forward, AimTransform.forward) > .5f)
{
rb.moveRotate(someTarget)
}
@kevojo that would work if rotation was limited to a single axis, but that's not the case
A bit late, but no. it is simply the angle between the direction vectors. They can be on any axis.