Deff_Dev

[Unity/C#] 오일러(Euler) 회전 이슈 본문

Unity(유니티)/유니티 공부

[Unity/C#] 오일러(Euler) 회전 이슈

Deff_a 2024. 6. 20. 22:42

이슈 사항

 

X축이 90도로 회전된 상태에서 상하, 좌우로 회전 시킨다면 x축만 회전되고, X축이 0도, 180도일 때는 상하는 X축 좌우는 Z축이 회전된다.

 

이 큐브를 스크립트에서 제어를 할 때, 값을 어떻게 넣어야 할까 ?


해결

이 문제를 해결하기 위해서는 유니티에서 오브젝트가 회전하는 방법에 대해 알고 있어야 한다.

 

회전할 때는 인스펙터 창에서의 Vector값을 이용하여 회전하는 것이 아닌 쿼터니언 값으로 회전하게 된다.

 

Quaternion * Vector를 이용하여 회전시킬 값을 구하는 것이다.

 

여기서 Quaternion는 회전 시킬 값을 의미하고 Vector는 회전을 적용시킬 오브젝트의 회전 값을 의미한다.

Quaternion currentRot = transform.rotation;
Quaternion targetRot = Quaternion.Euler(90,0,0)*currentRot ;

 

위와 같이 코드를 작성한다면 현재 오브젝트를 X축으로 90도 만큼 회전시킨 Quaternion값이 나오게 된다.

 

주의해야될 점은 Quaternion는 행렬이기 때문에 교환 법칙이 성립되지 않는다.

즉,  Q * V 순서를 지켜줘야 원하는 방향으로 회전하게 된다. == 회전 시킬 오브젝트의 회전 값은 맨 오른쪽에 나와야된다.

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;

public enum ERotateType{RotateX, RotateZ} // X가 상하, Z가 좌우회전
public class CubeRotationEventHandler : MonoBehaviour
{
    
    [Header("# Rotation Info")]
    [SerializeField] private float rotationDuration;
    [SerializeField] private float delayDuration;

    private Coroutine rotateCubeCoroutine;
    private WaitForSeconds wait;
    private Quaternion targetRot;
    private Quaternion currentRot;
    private Dictionary<ERotateType, Vector3> rotateDic;
    
    private void Awake()
    {
        wait = new WaitForSeconds(delayDuration);
        rotateDic = new Dictionary<ERotateType, Vector3>
        {
            { ERotateType.RotateX, new Vector3(-90, 0, 0) },
            { ERotateType.RotateZ, new Vector3(0, 0, -90) }
        };
    }
    
    
    public void RotateCube(ERotateType rotateType) // 카메라, 큐브효과
    {
        if (rotateCubeCoroutine != null)
        {
            StopCoroutine(rotateCubeCoroutine);
        }
        
        rotateCubeCoroutine = StartCoroutine(RotateCubeCoroutine(rotateType));
    }

    private IEnumerator RotateCubeCoroutine(ERotateType rotateType)
    {
        yield return wait;
        
        float currentTime = 0f;
        Quaternion currentRot = transform.rotation;
        Quaternion targetRot = Quaternion.Euler(rotateDic[rotateType])*currentRot ;
        
        while (currentTime < rotationDuration) // 회전
        {
            currentTime += Time.deltaTime;
            transform.rotation = Quaternion.Slerp(currentRot, targetRot, currentTime / rotationDuration);
            yield return null;
        }
        transform.rotation = targetRot;

        yield return wait;
    }
}

 

코드를 이런식으로 작성한다면 큐브가 원하는 방향으로 잘 회전되는 것을 확인할 수 있다.


 

3D 프로젝트를 하면 할수록 회전은 구현할 때마다 꼭 하나씩 이슈가 생기는 것 같다.