Unity/루빅스 큐브 개발 일지

[Unity] 루빅스 큐브 회전

suppresswisely 2025. 1. 19. 17:51

요약

루빅스 큐브가 어떻게 맞춰졌는지 보기 위해서는 큐브 전체를 회전하여 확인하여야 한다. 이를 위해 Target이라는 기준점을 활용하여 큐브를 전체 회전시키고 정렬하는 알고리즘을 작성하였다.


루빅스 큐브 회전

시작전에 알아야 할 사실은 루빅스 큐브에는 Target이 존재하는데 이는 루빅스 큐브를 회전한 수 정렬에 필요한 요소이다.

RotateBigCube.cs

public class RotateBigCube : MonoBehaviour
{
    Vector2 firstPressPos;
    Vector2 secondPressPos;
    Vector2 currentSwipe;
    Vector3 previousMousePosition;
    Vector3 mouseDelta;

    public GameObject target;
    float speed = 200f;

    void Update()
    {
        Swipe();
        Drag();
    }

firstPressPos: 처음 마우스를 클릭한 지점
secondPressPos: 다음 마우스를 클릭한 지점
currentSwipe: 마우스의 클릭하고 놓은 지점의 방향값
previousMousePosition: 루빅스 큐브를 회전시키기 위해 이전값을 저장함
mouseDelta: 저장된 마우스 이전값과 현재값을 통해 변화량을 구함
target: 루빅스 큐브를 90도 각도로 정렬시키기 위한 기준

 

    // Swipe(); Drag();는 우클릭을 통해 작동하는 함수
    // 마우스를 클릭하는 중을 인식하여 큐브를 돌리는 방향을 인식
    // 미리 회전할 부분을 보여주는 역할
    void Drag()
    {
        // 마우스 클릭하기 전의 값을 통해 내가 움직이는 거리를 확인하여 방향을 회전
        if (Input.GetMouseButton(1))
        {
            mouseDelta = Input.mousePosition - previousMousePosition;

            mouseDelta *= 0.1f;
            transform.rotation = Quaternion.Euler(mouseDelta.y, -mouseDelta.x, 0) * transform.rotation;
        }
        else
        {
            // Swipe함수에서 돌아간 target 루빅스 큐브와 실제 루빅스 큐브각도가 맞지 않을 경우 
            //큐브를 Time.deltaTime을 통해 돌아가는 애니메이션을 보여줌
            if (transform.rotation != target.transform.rotation)
            {
                var step = speed * Time.deltaTime;
                transform.rotation = Quaternion.RotateTowards(transform.rotation, target.transform.rotation, step);
            }
        }
        // 마우스 클릭하기 전의 값을 저장
        previousMousePosition = Input.mousePosition;
    }

Drag()는 루빅스 큐브를 회전시키기 위해 변화량을 구해 즉각적으로 회전시킨다. 다만 루빅스 큐브의 기준점과 같지 않다면 각도를 맞추기 위해 돌아간다.

 

    // 마우스 클릭한 순간, 마우스를 때는 순간을 기억하여 한번에 루빅스 큐브를 돌림
    void Swipe()
    {
        //마우스 클릭순간을 인식후 기억
        if (Input.GetMouseButtonDown(1))
        {
            firstPressPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
        }

        //마우스 클릭후 클릭한 순간의 값을 활용하여 큐브를 회전
        if (Input.GetMouseButtonUp(1))
        {
            secondPressPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
            currentSwipe = new Vector2(secondPressPos.x - firstPressPos.x, secondPressPos.y - firstPressPos.y);
            currentSwipe.Normalize();

            if (LeftSwipe(currentSwipe))
            {
                target.transform.Rotate(0, 90, 0, Space.World);
            }
            else if (RightSwipe(currentSwipe))
            {
                target.transform.Rotate(0, -90, 0, Space.World);
            }
            else if (UpLeftSwipe(currentSwipe))
            {
                target.transform.Rotate(90, 0, 0, Space.World);
            }
            else if (UpRightSwipe(currentSwipe))
            {
                target.transform.Rotate(0, 0, -90, Space.World);
            }
            else if (DownLeftSwipe(currentSwipe))
            {
                target.transform.Rotate(0, 0, 90, Space.World);
            }
            else if (DownRightSwipe(currentSwipe))
            {
                target.transform.Rotate(-90, 0, 0, Space.World);
            }
        }
    }

Swipe()는 루빅스 큐브의 기준점을 회전시키는 알고리즘으로 마우스가 클릭을 통해 얼마나 돌아간 방향값을 구하고 단위 벡터로 만들어 이를 활용하여 어느 쪽으로 돌렸는지 확인하는 알고리즘이다.

 

    // 벡터의 정규화를 통한 값을 받아 어느 방향으로 회전시킬지 정하는 함수
    bool LeftSwipe(Vector2 swipe)
    {
        return currentSwipe.x < 0 && currentSwipe.y > -0.5f && currentSwipe.y < 0.5f;
    }
    bool RightSwipe(Vector2 swipe)
    {
        return currentSwipe.x > 0 && currentSwipe.y > -0.5f && currentSwipe.y < 0.5f;
    }
    bool UpLeftSwipe(Vector2 swipt)
    {
        return currentSwipe.y > 0 && currentSwipe.x < 0f;
    }
    bool UpRightSwipe(Vector2 swipt)
    {
        return currentSwipe.y > 0 && currentSwipe.x > 0f;
    }
    bool DownLeftSwipe(Vector2 swipt)
    {
        return currentSwipe.y < 0 && currentSwipe.x < 0f;
    }
    bool DownRightSwipe(Vector2 swipt)
    {
        return currentSwipe.y < 0 && currentSwipe.x > 0f;
    }
}

해당 함수들은 단위 벡터를 이용하여 어느 방향으로 돌아갔는지 확인하는 함수들이다.