Search Unity

Cube Rotation Using Quaternion

Discussion in 'Scripting' started by Deleted User, Oct 14, 2021.

  1. Deleted User

    Deleted User

    Guest

    Hi,

    I have the following snippet of code, and amongst other things, it rotates a cube using Euler angles (180 degrees in the chosen direction), visually it seems to work.

    Now, if I place a visual test on the cube, for instance, a smaller cube without a box collider on top, it still works, flips 180, but then the cube is always upside down, meaning it never fully flips back up (180), even though it goes through the rotation animation again, I'm just testing 'right' movement for now, but all other directions do the same thing ?

    Any ideas or suggestions on how to rotate 'back' again, if I'm 'already' rotated ? Thanks.

    Code (CSharp):
    1.     IEnumerator CubeMovement(MoveDirection moveDirection, float duration)
    2.     {
    3.         canMove = false;
    4.         float progress = 0f;
    5.  
    6.         Quaternion endRotation = Quaternion.Euler(0, 0, 0);
    7.         Vector3 targetPosition = new Vector3(currentCubePosition.x + Distance, currentCubePosition.y, currentCubePosition.z);
    8.  
    9.         if (moveDirection == MoveDirection.UP)
    10.         {
    11.             endRotation = Quaternion.Euler(-180, 0, 0);
    12.             targetPosition = new Vector3(currentCubePosition.x, currentCubePosition.y, currentCubePosition.z + Distance);
    13.         }
    14.  
    15.         else if (moveDirection == MoveDirection.DOWN)
    16.         {
    17.             endRotation = Quaternion.Euler(180, 0, 0);
    18.             targetPosition = new Vector3(currentCubePosition.x, currentCubePosition.y, currentCubePosition.z - Distance);
    19.         }
    20.  
    21.         else if (moveDirection == MoveDirection.LEFT)
    22.         {
    23.             endRotation = Quaternion.Euler(0, 0, -180);
    24.             targetPosition = new Vector3(currentCubePosition.x - Distance, currentCubePosition.y, currentCubePosition.z);
    25.         }
    26.  
    27.         else if (moveDirection == MoveDirection.RIGHT)
    28.         {
    29.             endRotation = Quaternion.Euler(0, 0, 180);
    30.             targetPosition = new Vector3(currentCubePosition.x + Distance, currentCubePosition.y, currentCubePosition.z);
    31.         }
    32.  
    33.         Vector3 endPosition = new Vector3(targetPosition.x, currentCubePosition.y, targetPosition.z);
    34.  
    35.         while (progress < duration)
    36.         {
    37.             progress += Time.deltaTime;
    38.  
    39.             float percent = Mathf.Clamp01(progress / duration);
    40.             float height = jumpHeight * Mathf.Sin(Mathf.PI * percent);
    41.  
    42.             transform.position = Vector3.Lerp(currentCubePosition, endPosition, percent) + new Vector3(0, height, 0);
    43.             transform.rotation = Quaternion.Lerp(currentCubeRotation, endRotation, percent);
    44.  
    45.             yield return null;
    46.         }
    47.  
    48.         currentCubePosition = new Vector3(transform.position.x, 0.5f, transform.position.z);
    49.         canMove = true;
    50.     }
    51. }
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    You don't seem to set currentCubeRotation after the while loop like you do the position?
     
    Deleted User likes this.
  3. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    I'm not sure I can picture what the issue is, unfortunately. Can you provide some diagrams, a gif or something?
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class GridHopRotation : MonoBehaviour
    7. {
    8.    public enum MoveDirection
    9.    {
    10.        RIGHT,
    11.        LEFT,
    12.        UP,
    13.        DOWN
    14.    }
    15.  
    16.    private bool canMove;
    17.    private Vector3 currentCubePosition;
    18.    private int currentCubePitch;
    19.    private int currentCubeRoll;
    20.  
    21.  
    22.    public float Distance;
    23.    public float jumpHeight;
    24.    public float Duration;
    25.  
    26.    void Start()
    27.    {
    28.        canMove = true;
    29.        currentCubePosition = transform.position;
    30.  
    31.        // This isn't the most reliable, ideally have your cube always at 0,0,0 rotation at the start
    32.        currentCubePitch = (int)transform.rotation.eulerAngles.x;
    33.        currentCubeRoll = (int)transform.rotation.eulerAngles.z;
    34.    }
    35.  
    36.    void Update()
    37.    {
    38.        if (canMove)
    39.        {
    40.            if (Input.GetKeyDown(KeyCode.UpArrow))
    41.                StartCoroutine(CubeMovement(MoveDirection.UP, Duration));
    42.  
    43.            else if (Input.GetKeyDown(KeyCode.DownArrow))
    44.                StartCoroutine(CubeMovement(MoveDirection.DOWN, Duration));
    45.  
    46.            else if (Input.GetKeyDown(KeyCode.LeftArrow))
    47.                StartCoroutine(CubeMovement(MoveDirection.LEFT, Duration));
    48.  
    49.            else if (Input.GetKeyDown(KeyCode.RightArrow))
    50.                StartCoroutine(CubeMovement(MoveDirection.RIGHT, Duration));
    51.        }
    52.    }
    53.  
    54.    IEnumerator CubeMovement(MoveDirection moveDirection, float duration)
    55.    {
    56.        canMove = false;
    57.        float progress = 0f;
    58.  
    59.        Vector3 targetPosition = new Vector3(currentCubePosition.x + Distance, currentCubePosition.y, currentCubePosition.z);
    60.  
    61.        int targetPitch = 0;
    62.        int targetRoll = 0;
    63.  
    64.        if (moveDirection == MoveDirection.UP)
    65.        {
    66.            targetPitch += 180;
    67.            targetPosition = new Vector3(currentCubePosition.x, currentCubePosition.y, currentCubePosition.z + Distance);
    68.        }
    69.  
    70.        else if (moveDirection == MoveDirection.DOWN)
    71.        {
    72.            targetPitch -= 180;
    73.            targetPosition = new Vector3(currentCubePosition.x, currentCubePosition.y, currentCubePosition.z - Distance);
    74.        }
    75.  
    76.        else if (moveDirection == MoveDirection.LEFT)
    77.        {
    78.            targetRoll += 180;
    79.            targetPosition = new Vector3(currentCubePosition.x - Distance, currentCubePosition.y, currentCubePosition.z);
    80.        }
    81.  
    82.        else if (moveDirection == MoveDirection.RIGHT)
    83.        {
    84.            targetRoll -= 180;
    85.            targetPosition = new Vector3(currentCubePosition.x + Distance, currentCubePosition.y, currentCubePosition.z);
    86.        }
    87.  
    88.        Vector3 endPosition = new Vector3(targetPosition.x, currentCubePosition.y, targetPosition.z);
    89.        Vector3 endRotation = new Vector3(targetPitch, 0f, targetRoll);
    90.  
    91.        while (progress < duration)
    92.        {
    93.            progress += Time.deltaTime;
    94.  
    95.            float percent = Mathf.Clamp01(progress / duration);
    96.            float height = jumpHeight * Mathf.Sin(Mathf.PI * percent);
    97.  
    98.            transform.position = Vector3.Lerp(currentCubePosition, endPosition, percent) + new Vector3(0, height, 0);
    99.            transform.Rotate((endRotation / duration) * Time.deltaTime, Space.World);
    100.  
    101.            yield return null;
    102.        }
    103.  
    104.        currentCubePosition = new Vector3(transform.position.x, 0.5f, transform.position.z);
    105.        currentCubePitch += targetPitch;
    106.        currentCubeRoll += targetRoll;
    107.  
    108.        transform.rotation = Quaternion.Euler(currentCubePitch, 0f, currentCubeRoll);
    109.  
    110.        canMove = true;
    111.    }
    112. }
    113.  
    This is working from what I can tell. I got rid of the lerp on the rotation because it's ambiguous (+180 degrees can go either "left" or "right" as they're both the shortest distance), and stored the angles separately to rebuild the rotation after the coroutine to the "proper" values.

    Let me know if you have any issues.
     
    Deleted User likes this.