💡 Quotation

벡터(Vector)는 물리학 및 공학에서 벡터는 위치, 속도, 힘 등과 같이 크기와 방향성을 갖는 물리량을 나타내는데 사용하는 기하학적 대상이다.

유니티에서 키보드의 입력을 받아 플레이어의 특정 방향으로 움직일 때 Normalize를 거친 벡터를 사용하라고 하는데 왜 그럴까? 궁금해서 글을 쓰게 되었습니다. 😄

Nomalize (정규화)

일단 제가 알고 있는 정규화는 0 ~ 1 범위로 표현하는 것을 정규화라고 알고 있습니다. 벡터의 정규화는 어떤 것을 의미할까요?

Vector3.Normalize()의 코드를 먼저 분석해 보겠습니다.

💡 Git: Unity-TechnologiesVector3의 코드를 볼 수 있습니다!

1
2
3
4
5
6
7
8
9
// Makes this vector have a ::ref::magnitude of 1.[MethodImpl(MethodImplOptionsEx.AggressiveInlining)]
public void Normalize()
{
    float mag = Magnitude(this);
    if (mag > kEpsilon)
        this = this / mag;
    else
        this = zero;
}								   

단순히 mag 값이 0보다 크다면 해당 값으로 나누어 저장을 합니다.

💡 Magnitude() 는 단순 벡터의 크기를 반환하는 함수입니다.

1
2
3
4
5
6
// *undoc* --- there's a property now
[MethodImpl(MethodImplOptionsEx.AggressiveInlining)]
public static float Magnitude(Vector3 vector) 
{ 
  return (float)Math.Sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z); 
}

x, y, z 축에 벡터의 크기를 나누어 최대 값이 1로 만드는 단순한 함수였습니다. 크기가 정규화 됐으므로 방향의 데이터만 남는 것이라고 생각할 수도 있겠습니다. 그럼 왜 키보드로부터 방향을 입력받은 후 정규화를 하라고 하는 것일까요?

🚀 정규화 하는 이유?

w, a, s, d 중 하나의 방향으로만 입력이 된다면(벡터의 크기 1) 필요가 없을 것입니다. 하지만 플레이어는 대각선의 방향으로도 움직일 수 있습니다. 이 때 사용자는 두 개의 키 조합으로 움직일테고, 이 때 Vector3의 크기는 1보다 큰 1.414213 이 될겁니다.

이 값을 transform.position에 더하거나 rigidbody.MovePostion() 에 입력한다면 당연히 수평/수직 방향보다 대각선으로 이동했을 때 더 빠르겠죠?

💡 Vector3의 값이 (1, 1, 0) 을 갖는다면 mag 값이 대략 1.414 값이 나오고 이를 각 축에 모두 나눈다면 (0.707, 0.707, 0) 정도의 값이 나오네요! 👍

Mathf.Lerp

정규화와 같이 많이 사용되는 함수 중 하나가 있습니다. 바로 Mathf.Lerp() 함수입니다.

이는 세 번째 인자로 들어온 정규화 값을 특정한 범위의 값으로 반환해 주는 선형 보간 함수인데요. 우선 0 ~ 1 범위로 만들어주는 정규화의 공식은 아래와 같습니다.

$$x = \frac{Value - Min}{Max - Min}$$

여기서 Lerp(minimum, maximum, normal) 함수는 단순히 특정 범위로 나타낼 수 있게 아래의 수식을 통해서 계산되게 됩니다! 😎

$$minimum + (maximum - minimum) * normal$$

💡 이 곳 에서 Lerp() 함수를 볼 수 있습니다!