Kiki Devlog

유니티 Quaternion slerp / Euler (카메라 회전) 본문

Unity/개념 정리 & 팁

유니티 Quaternion slerp / Euler (카메라 회전)

kimkiki 2021. 7. 18. 23:21
728x90
  • 오늘 배운 점을 정리할 겸 쓰는 것이기 때문에 틀린 부분이 있을 수 있음. 

NPC와의 대사 중 스토리 진행을 위해 카메라가 NPC와 배경을 비추며 자연스럽게 회전하는(애니메이션 같은) 모습을 연출하고 싶었음.

카메라의 자연스러운 회전을 위해 Quaternion을 쓰기로 함.

일단 우리가 쓰는 transform.rotation은 quaternion단위임.

그래서

transform.rotation = Quaternion.Euler(10,20,30); // euler을 quaternion으로 바뀌주는 함수

이런 식으로 사용할 수 있음.

 

Quarternion 에는 lerp, Slerp 가 있는데 아래 이미지로 보면 차이가 뭔지 알 수 있음.

"Slerp interpolates two Quats accurately and precisely which requires more power, Lerp interpolates two quats unevenly. " (https://forum.unity.com/threads/what-is-the-difference-of-quaternion-slerp-and-lerp.101179/)

추측상 lerp는 시작과 끝에서 속도가 달라질듯...?

(무조건 직선을 n등분해서 vector3값을 알려주니까 각각의 각도는 천차만별인거지!)

-> 자연스러운 회전을 위해 Slerp를 쓰는 것을 선택. (근데 체감상 비슷해)

 

 

 

 

 

 

 

 

아래는 성공한 코드임.

Quaternion.Euler 과 Quaternion.LookRotation 을 똑같다고 생각해서 한참걸렸다.

	Quaternion to;
    float rotateSpeed;

    bool isRotating;//카메라가 도는중일때 true
    
    // Update is called once per frame
    void Update()
    {
        camRotate();
    }

    public void setCamMove(Vector3 camPos,Vector3 fromV, Vector3 toV,float _rotateSpeed,float animPlayTime)
    {
        cameraManager.animCamOn(); // 애니메이션 재생용 카메라를 켜는 함수
        transform.position = camPos; // 애니메이션 카메라의 위치를 설정

        Vector3 fromVec = fromV - transform.position; // 시작 Vec
        Vector3 toVec = toV - transform.position;     // 도착 Vec
        toVec.y = fromVec.y; //시점이 위나 아래로 떨어지지 않도록 높이를 맞춰줌
        
        to = Quaternion.LookRotation(toVec); //euler 각도인 toVec을 물체의 '앞 방향' 으로 설정. (toVec의 방향이 cam이 앞을 볼때의 방향이야~)
        //to = Quaternion.Euler(toVec); //이렇게 쓰면 안됨. (내가 헷갈린 부분)
        rotateSpeed = _rotateSpeed; //카메라가 회전하는 속도 설정

        transform.rotation = Quaternion.LookRotation(fromVec); //시작 할때 카메라가 fromVec을 바라보고 시작하게함.
        isRotating = true;

        
        Invoke("stopRotating", animPlayTime);//animPlayTime 초 뒤에 회전을 멈추게하는 함수를 호출.
    }

    void stopRotating()
    {
        isRotating = false;
    }
    
    void camRotate()//지정된 초(animPlayTime)만큼 도는 함수
    {
        if (isRotating)
            transform.rotation = Quaternion.Slerp(transform.rotation, to, rotateSpeed * Time.deltaTime);  
    }

 

좀 지저분한 코드인것 같지만 지금 내 최선임! 

Quaternion.Euler 은 안되고 Quaternion.LookRotation은 되는 이유!(100 % 내 추측)

euler은 카메라를 원점으로 생각하지 않은 절대좌표에서의 백터값이고

lookRotation은 카메라를 원점으로 생각하는 상대좌표에서의 백터값을 반환해서

lookRotation이 내가 원하는 각도만큼 카메라를 돌리는 것에 적합한 것 같다.

Comments