- Home /
Object doesn't rotate properly
So I have a cube that can be rolled to the right or forward. In order to avoid overshooting, I'm using Quaternion.RotateTowards to roll the cube. Here's the code:
using UnityEngine;
using System.Collections;
public class CubeMovement : MonoBehaviour
{
public GameObject colliderPlane;
Quaternion planeDefaultRotation;
public AnimationCurve yValueCurve;
float animationTime;
float animCurveTime;
void Start()
{
planeDefaultRotation = colliderPlane.transform.rotation;
Keyframe lastKeyframe = yValueCurve.keys[yValueCurve.length - 1];
animCurveTime = lastKeyframe.time + 1;
animationTime = animCurveTime / 60;
}
public IEnumerator RollForward()
{
Vector3 finalPosition = transform.position + new Vector3(0, 0, 10);
Quaternion finalRotation = transform.rotation * Quaternion.AngleAxis(90, Vector3.right);
for (float currentTime = 0; currentTime < animationTime; currentTime += Time.deltaTime)
{
float currentFrameTime = (currentTime * animCurveTime) / animationTime;
transform.position = new Vector3(transform.position.x, yValueCurve.Evaluate(currentFrameTime), transform.position.z + (10 * Time.deltaTime / animationTime));
transform.rotation = Quaternion.RotateTowards(transform.rotation, finalRotation, 90 * Time.deltaTime / animationTime);
yield return new WaitForEndOfFrame();
}
transform.position = finalPosition;
colliderPlane.transform.position = transform.position;
colliderPlane.transform.rotation = planeDefaultRotation;
yield return null;
}
public IEnumerator RollToRight()
{
Vector3 finalPosition = transform.position + new Vector3(10, 0, 0);
Quaternion finalRotation = transform.rotation * Quaternion.AngleAxis(90, Vector3.back);
for (float currentTime = 0; currentTime < animationTime; currentTime += Time.deltaTime)
{
float currentFrameTime = (currentTime * animCurveTime) / animationTime;
transform.position = new Vector3(transform.position.x + (10 * Time.deltaTime / animationTime), yValueCurve.Evaluate(currentFrameTime), transform.position.z);
transform.rotation = Quaternion.RotateTowards(transform.rotation, finalRotation, 90 * Time.deltaTime / animationTime);
yield return new WaitForEndOfFrame();
}
transform.position = finalPosition;
colliderPlane.transform.position = transform.position;
colliderPlane.transform.rotation = planeDefaultRotation;
yield return null;
}
If the cube only moves in one direction, the cube rotates properly. However if it changes to any other direction the cube doesn't rotate like it should. For example, if the cube rolls forward and in no other direction it rolls in the forward direction. However, if the player moves it forward and the moves it to the right , the cube rotates sideways. It seems these happens because the rotation axis change their position too
I've tried several methods (transform methods, Quaternion.FromToRotation, Quaternion.AngleAxis, animation curves...) but the problem still persists. Any ideas?
Answer by unity_cfUW-mhVK73Mcg · May 17 at 04:37 PM
I've fixed the issue, the thing is that each rotation changes the orientation of each rotation axis but I assumed that wasn't the case. To fix this, I now rotate an empty object that is the cube's parent. Once a roll is finished, I detach the cube from the parent, I reset the parent's orientation and reattach the cube. It works every roll.
In case someone has to deal with rotations, here's the code for rolling forward:
IEnumerator RollForward()
{
Vector3 finalPosition = transform.position + new Vector3(0, 0, 10);
Quaternion finalRotation = transform.rotation * Quaternion.AngleAxis(90, transform.right);
for (float currentTime = 0; currentTime < animationTime; currentTime += Time.deltaTime)
{
float currentFrameTime = (currentTime * positionCurveTime) / animationTime;
Vector3 nextPosition = new Vector3(transform.position.x, positionCurve.Evaluate(currentFrameTime), transform.position.z + (24 * Time.deltaTime));
Quaternion nextRotation = Quaternion.RotateTowards(transform.rotation, finalRotation, 90 * Time.deltaTime / animationTime);
transform.SetPositionAndRotation(nextPosition, nextRotation);
yield return new WaitForEndOfFrame();
}
transform.position = finalPosition;
cubeObject.transform.parent = null;
transform.rotation = Quaternion.identity;
cubeObject.transform.SetParent(transform);
Vector3 selectionPlaneCenter = new Vector3(transform.position.x, transform.position.y + 5, transform.position.z);
selectionPlane = new Plane(Vector3.up, selectionPlaneCenter);
yield return null;
}