So I'm trying to build a simple mechanic where the player see's 3 sides of a cube at a time: top, left and front(I called the front-side "Right" in my code, due to the orthographic view). The player can click on the front side or left side of the cube to rotate the cube so that the side that was pressed moves and becomes the top face. I want to smooth/animate the rotation.
The red faces are the faces that the user can click on.
My Logic seems to work quite well when I click on the left face (Rotating along the x axis), but doesn't seem to work well for the front/right face(It usually works once and then does weird stuff on the next click, this is on the z-axis)
public class CubeRotator : MonoBehaviour
{
private const float STOP_THRESHHOLD = 0.1f;
private const float ROTATE_AMOUNT = 90f;
[SerializeField, Header("Touch Quads Colliders")]
private Collider touchQuadLeft;
[SerializeField]
private Collider touchQuadRight;
[SerializeField, Space(10)]
private float timeToRotate;
private bool mustRotateLeft = false;
private bool mustRotateRight = false;
private float targetX = 0.0f;
private float targetZ = 0.0f;
private float xVelocity = 0.0F;
private float zVelocity = 0.0F;
int layerMask;
private void Start()
{
layerMask = LayerMask.GetMask("Touch Quad");
}
void Update()
{
ListenForTouch();
RotateCube();
}
private void ListenForTouch()
{
if (Input.GetMouseButtonDown(0))
{
Vector2 touchPoint = Input.mousePosition;
RaycastHit rayCastHit;
Ray ray = Camera.main.ScreenPointToRay(touchPoint);
if (Physics.Raycast(ray, out rayCastHit, 150f, layerMask))
{
if (rayCastHit.collider == touchQuadLeft)
{
mustRotateLeft = true;
targetZ = targetZ - ROTATE_AMOUNT;
zVelocity = 0f;
}
else if (rayCastHit.collider == touchQuadRight)
{
mustRotateRight = true;
targetX = targetX + 90f;
xVelocity = 0f;
}
}
}
}
private void RotateCube()
{
float zAngle = transform.rotation.eulerAngles.z;
float xAngle = transform.rotation.eulerAngles.x;
if (mustRotateLeft)
{
zAngle = Mathf.SmoothDampAngle(zAngle, targetZ, ref zVelocity, timeToRotate);
if (Mathf.Abs(zVelocity) <= STOP_THRESHHOLD)
{
mustRotateLeft = false;
}
}
if (mustRotateRight)
{
xAngle = Mathf.SmoothDampAngle(xAngle, targetX, ref xVelocity, timeToRotate);
if (Mathf.Abs(xVelocity) <= STOP_THRESHHOLD)
{
mustRotateRight = false;
}
}
transform.rotation = Quaternion.Euler(xAngle, 0f, zAngle);
}
}
Inspector Values:
I've tried several things, the only problem I can think of is, gimbal lock. Thanks in advance.
Quaternion.Euler
orAngleAxis
. Then update your target by applying this change to it:currentTarget = rotationChange * currentTarget;
You can then useQuaternion.Lerp
orRotateTowards
to blend smoothly to this target rotation. \$\endgroup\$