[3D,Transform]2-2. Vector3

0

유니티 엔진

목록 보기
20/21

Vector

벡터에 대해서 수학이나 물리학에서는 여러 복잡한 정의가 존재하는데 간단하게 요약하자면 특정한 공간에서의 방향과 크기를 표현하는 도구로서 주로 화살표로 표시되는 개념입니다.

벡터의 활용

벡터는 방향과 크기를 표현하는 도구라고 이야기했는데, 이것을 이용해 여러 가지 용도로 활용된다.

  • 첫 번째 활용법은 방향과 속도(방향 벡터)입니다. 여기서 속도는 스칼라에 해당합니다.
    방향은 벡터가 표시하는 좌표까지 화살표를 그리는 것으로 방향을 쉽게 알 수 있습니다.

    이동거리 = 방향 * 속도

    방향에 속도를 곱해주면 이동하고자하는 방향과 속력, 즉, 속도의 개념으로 활용되는 것입니다. 이것을 통해 우리는 좌표계를 다루며 캐릭터를 어느 방향으로 이동시킬지, 얼마만큼의 속도로 이동시킬지로 활용하였습니다.

  • 두 번째 활용법은 좌표(위치 벡터)입니다.
    유니티에서는 X축 Y축 Z축이 교차하는 지점(0,0,0)을 공간의 중심이라고 지정해두었습니다.
    V1(3, 5, 1) 위치에 어떤 오브젝트가 있다면, 그 오브젝트는 월드 좌표계(3.0, 5.0, 1.0)의 위치에 있다고 말할 수 있습니다.
    위치 벡터는 transform.position을 통해 접근할 수 있습니다.

벡터의 계산

벡터의 덧셈과 뺄셈

두 개의 벡터는 서로 더하거나 뺄 수 있습니다.

우선 벡터의 덧셈을 살펴보자. 위 그림을 보면 (1, 2)의 V1과 (2, 1)의 V2를 더하면 (3, 3)의 V3가 나오는 것을 볼수 있습니다. V1 지점에서 V2 만큼 이동했다고 여기면 됩니다.

또 다른 관점에서 살펴보면 두 벡터의 합은 서로 다른 방향의 두 힘이 충돌했을 때의 그 합쳐진 힘의 진행 방향으로 해석될 수도 있습니다.


벡터의 뺄셈은 역시 (1, 2)인 V1에서 (2, 1)인 V2를 빼면 (-1, 1)인 V3가 나옵니다.
다만 여기서 기억할 점은 이렇게 결과 값으로 나온 V3가 V2 지점에서 시작하여 V1 방향으로 이동하는 V3'와 길이와 방향이 모두 같다는 것입니다. 이것을 이용하면 V1과 V2 사이의 거리, V2에서 V1으로 가는 방향등을 구할 수 있습니다.

벡터와 스칼라의 곱셈

벡터는 좌표로서 공간 상에서 방향과 크기를 의미하지만 스칼라는 크기 만을 가지는 값입니다.

(1, 1)인 V1에 4인 스칼라 S를 곱하면 V1의 각 원소에 S를 곱하여 (4, 4)인 V2를 얻게 됩니다. 이렇게 벡터에 스칼라를 곱하는 계산은 주로 벡터의 크기를 원하는대로 늘이거나 줄이는 등의(예: 오브젝트 이동) 계산이나, 벡터에 -1을 곱해서 현재 벡터의 반대 방향을 구하는데 주로 사용됩니다.

벡터의 길이


벡터의 길이를 구하는 공식은 위와 같습니다. 벡터의 각 원소를 제곱한 뒤, 모두 더하여 제곱근을 구하면, 벡터의 길이가 나옵니다. 이것은 사실 피타고라스의 정리에서 유도된 빗변의 길이를 구하는 공식입니다. 벡터는 항상 각 축을 대상으로 직각을 이루는 직각 삼각형의 형태이기 때문에 이 공식으로 길이를 구할 수 있습니다.


3차원 벡터에 대한 공식은 2차원 공식에 z축 좌표를 추가해서 계산하면 됩니다.

벡터의 정규화(Normalize)

벡터의 정규화는 현재 벡터의 방향을 유지한 채로 벡터의 길이를 1로 만드는 것을 의미하며, 이를 단위 벡터라고 부릅니다.

단위 벡터를 구하려면 벡터의 각 원소를 벡터의 길이로 나누어 주면 됩니다.

이런 단위벡터는 정확히 벡터의 방향만을 추출하고자 할 때 사용되는데, 주 사용처를 이야기 해보자면, 만약 캐릭터를 마우스의 방향으로 이동시키려고 할 때, (마우스 위치) - (캐릭터 위치)로 캐릭터에서 마우스 위치 방향을 찾아낼 것입니다. 그런데 이 벡터를 그대로 사용하면 마우스의 거리가 멀어지면 멀어질 수록 이 이동 벡터의 길이가 길어지기 때문에 마우스와 캐릭터의 거리가 멀면 캐릭터가 빨라지고 가까워지면 캐릭터가 느려지는 문제가 발생합니다.

이것을 해결하기 위해 (마우스 위치) - (캐릭터 위치)로 찾아낸 방향을 정규화해서 단위 벡터로 만든 다음에 캐릭터의 이동 속도만 곱해주면 캐릭터가 일정한 속도로 이동하게 됩니다.

벡터의 내적(Dot Product)

점곱(dot product), 내적(inner product)이라고 부르는 계산으로 계산 결과 값으로 벡터가 아닌 단일 값, 즉 스칼라 값을 내는 계산입니다. 때문에 스칼라 곱이라고도 부르는데, 벡터와 스칼라의 곱셈과 헷갈려서는 안됩니다.

벡터의 각 원소끼리 곱한 뒤, 모두 더하는 것으로 벡터의 내적을 구할 수 있습니다.

이렇게 나온 계산 결과의 의미는 내적의 값이 0이면 두 벡터의 각이 90도이고, 0보다 크면 두 벡터 사이의 각도가 90도보다 작고, 0보다 작으면 각도가 90도보다 크다는 의미입니다. 여기에 삼각함수를 이용하면 두 벡터 사이의 각도를 구할 수 있습니다.

벡터의 외적(Cross Product)

가위곱(cross product), 외적(outer product)이라고 부르는 계산으로 두 벡터와 모두 직교하는, 즉 두 벡터와의 각이 모두 90도를 이루는 벡터를 결과값으로 내며, 3차원 공간에서만 성립하는 계산입니다.


V1과 V2에 대해서 직교하는 벡터는 V3, V4 둘 다 될 수 있는데, 이 결과는 왼손 좌표계를 사용하느냐, 오른손 좌표계를 사용하느냐에 따라 결과가 달라집니다. 왼손 좌표계에서 V2 X V1의 결과값은 V3로 나오고 오른손 좌표계에서는 V4로 나온다. 이렇게 나온 벡터를 법선 벡터(Normal Vector)라고 부릅니다.

그래서 벡터의 외적은 그림과 같이 한 면이 바라보는 방향을 구하는 용도로 주로 사용됩니다.

유니티 엔진의 벡터

유니티 엔진에서의 벡터에 대해서 알아보겠습니다.
위에서 공부한 내용을 직접 구현할 필요없이 유니티에서 제공하는 벡터 관련기능을 사용하면 됩니다.

Vector2,Vector3

Vector2 vector2 = new Vector2();
vector2.x = 1f;
vector2.y = 1f;

Vector3 vector3 = new Vector3();
vector3.x = 1f;
vector3.y = 1f;
vector3.z = 1f;

위의 코드 예시는 유니티에서 사용되는 Vector2 구조체와 Vector3 구조체입니다. Vector2 구조체는 2차원 평면 공간에 속하는 벡터로 X축의 좌표를 표시하기 위한 x 변수와, Y축의 값을 표시하기 위한 y 변수를 가집니다. Vector3 클래스는 여기에 더해 Z축을 표시하는 z 변수까지 가집니다.

Vector2는 대부분 UI 같은 2D 공간이나 2D 게임을 제작할 때 사용되고, Vector3는 일반적인 3D 공간에서 사용됩니다.

벡터의 덧셈과 뺄셈

벡터의 덧셈과 뺄셈은 간단하게 일반 덧셈과 뺄셈을 하듯이 연산자를 사용하면 바로 구할 수 있습니다.

Vector3 v1 = new Vector3(1f, 2f, 0f);
Vector3 v2 = new Vector3(2f, 1f, 0f);

// 벡터의 덧셈
Debug.Log("v1 + v2 = " + (v1 + v2));

// 벡터의 뺄셈
Debug.Log("v1 - v2 = " + (v1 - v2));

결과
v1 + v2 = (3.0, 3.0, 0.0)
v1 - v2 = (-1.0, 1.0, 0.0)

벡터와 스칼라의 곱셈

벡터와 스칼라, 단일 정수 혹은 단일 실수와의 곱셈 역시 일반 계산과 같이 간단합니다.

Vector3 v1 = new Vector3(1f, 1f, 0f);
int scalar = 4;

// 벡터와 스칼라의 곱셈
Debug.Log("v1 * scalar = " + (v1 * scalar));

결과
v1 * scalar = (4.0, 4.0, 0.0)

벡터의 길이

벡터의 길이는 Vector3 구조체에 포함되어 있는 magnitude 프로퍼티를 통해서 가져올 수 있다. 이것은 Vector2에서도 똑같습니다.

Vector3 v1 = new Vector3(2f, 2f, 0f);

// 벡터의 길이
Debug.Log("length of v1 = " + (v1.magnitude));

결과
length of v1 = 2.828427

벡터의 정규화

Vector3 구조체의 normalized 프로퍼티를 이용하면 정규화된 단위 벡터를 가져올 수 있습니다.
magnitude 프로퍼티를 다시 사용해보면 단위 벡터의 길이가 1임을 확인할 수 있습니다.

Vector3 v1 = new Vector3(2f, 2f, 0f);

// 정규화된 단위 벡터
Vector3 normalizedVector = v1.normalized;
Debug.Log("||v1|| = " + normalizedVector);

// 단위 벡터의 길이 확인
Debug.Log("length of ||v1|| = " + normalizedVector.magnitude);

결과
||v1|| = (0.7, 0.7, 0.0)
length of ||v1|| = 1

벡터의 내적

코드에 정의된 각 벡터는 그림과 같습니다.

벡터의 내적을 구하려면 Vector3 클래스의 정적 함수인 Dot 함수를 사용하면 됩니다.

Vector3 v1 = new Vector3(2f, 0f, 0f);
Vector3 v45 = new Vector3(1f, 1f, 0f);
Vector3 v90 = new Vector3(0f, 2f, 0f);
Vector3 v135 = new Vector3(-1f, 1f, 0f);

// 벡터의 내적
Debug.Log("v1 . v45 = " + Vector3.Dot(v1, v45));
Debug.Log("v1 . v90 = " + Vector3.Dot(v1, v90));
Debug.Log("v1 . v135 = " + Vector3.Dot(v1, v135));

// 두 벡터 사이의 각도
Debug.Log("v1 . v45 = " + Vector3.Angle(v1, v45));
Debug.Log("v1 . v90 = " + Vector3.Angle(v1, v90));
Debug.Log("v1 . v135 = " + Vector3.Angle(v1, v135));

벡터의 내적에 대해서 설명했듯이, v1과 v45 사이의 각도는 90도 보다 작기 때문에 0보다 큰 값이 나왔고, v1과 v90 사이 각은 정확히 90도이기 때문에 0, v1과 v135 사이 각은 90도보다 커서 0보다 작은 값이 나온 것을 확인할 수 있습니다.

덤으로 Vector3의 또 다른 정적 함수인 Angle 함수를 사용하면 두 벡터 사이의 각을 얻을 수 있습니다.

결과
벡터의 내적
v1 . v45 = 2
v1 . v90 = 0
v1 . v135 = -2
두 벡터 사이의 각도
v1 . v45 = 45
v1 . v90 = 90
v1 . v135 = 135

벡터의 외적

벡터의 외적은 Vector3 클래스의 정적 함수인 Cross 함수를 통해서 구할수 있습니다.

Vector3 v1 = new Vector3(2f, 0f, 0f);
Vector3 v2 = new Vector3(0f, 0f, 2f);

// 벡터의 외적
Debug.Log("v1 X v2 = " + Vector3.Cross(v1, v2));

결과
v1 X v2 = (0.0, -4.0, 0.0)

0개의 댓글