벡터¶
소개¶
이 튜토리얼은 게임 개발에 적용되는 선형대수에 대한 짧고 실용적인 소개입니다. 선형 대수란 벡터와 벡터 사용에 대한 학문입니다. 벡터는 2D 및 3D 개발 모두에서 많은 응용방법이 있으며 Godot는 이를 광범위하게 사용합니다. 벡터 수학에 대한 올바른 이해는 강력한 게임 개발자가 되기 위해 필수적입니다.
참고
이 튜토리얼은 선형대수에 관한 공식 교과서가 절대 아닙니다. 우리는 단지 그것이 어떻게 게임 개발에 적용되는지 지켜볼 것입니다. 수학에 대한 자세한 내용은 https://www.khanacademy.org/math/linear-algebra을 참조하십시오
좌표계 (2차원)¶
2차원 공간에서, 좌표계들은 가로축(x
)과 세로축(y
)을 사용하여 정의됩니다. 2차원 공간에서의 특정한 위치는 (4,3)
과 같이 한 쌍의 값으로 쓰여집니다.

참고
컴퓨터 그래픽을 처음 접하는 사람이라면 아마 수학 수업에서 배웠듯이 양의``y" 축이 위쪽이 아니라 **아래쪽**을 가리키는 것이 이상하게 보일지도 모릅니다. 그러나 대부분의 컴퓨터 그래픽 응용 프로그램에서는 일반적으로 이러한 현상이 발생합니다.
2D 평면의 모든 위치는 이러한 방식으로 한 쌍의 수들로 식별할 수 있습니다. 그러나 우리는 또한 (4, 3)
의 위치를 (0, 0)
또는 원점으로부터의 오프셋으로 생각할 수 있습니다. 원점에서 점까지 점을 가리키는 화살표를 그리세요:

이것은 벡터입니다. 벡터는 유용한 많은 정보들을 보여줍니다. 점이 (4, 3)에 있다고 알려줄 뿐 아니라, 우리는 각도 'θ' 그리고 길이 (또는 크기) 'm' 또한 생각해낼 수 있습니다. 이러한 경우 화살표는 **위치 벡터**로, 원점에 상대적인 공간의 위치를 나타냅니다.
벡터에 대해 고려해야 할 매우 중요한 점은 벡터가 상대적인 방향과 크기만 나타낸다는 것입니다. 벡터의 위치에 대한 개념이 없습니다. 다음 두 벡터는 동일합니다:

두 벡터 모두 시작점으로 부터 오른쪽으로 4만큼 아랫쪽으로 3만큼 의 단위를 나타냅니다. 평면에서 벡터를 그리는 것은 중요하지 않습니다. 이것은 항상 상대적인 방향과 크기를 나타냅니다.
벡터 연산¶
당신은 둘 중 하나의 방법(x 및 y 좌표 또는 각도 및 크기)을 사용하여 벡터를 참조할 수 있지만, 프로그래머는 편의를 위해 일반적으로 좌표 표기법을 사용합니다. 예를 들어, Godot에서 원점은 화면의 왼쪽 상단 모서리이고, Node2D
라는 2차원의 노드를 400픽셀 오른쪽, 300픽셀 아래로 배치하려면 다음 코드를 사용하십시오:
$Node2D.position = Vector2(400, 300)
var node2D = GetNode<Node2D>("Node2D");
node2D.Position = new Vector2(400, 300);
Godot supports both Vector2 and Vector3 for 2D and 3D usage, respectively. The same mathematical rules discussed in this article apply to both types.
멤버 접근¶
벡터의 각각의 구성요소는 이름으로 직접 접근할 수 있다.
# create a vector with coordinates (2, 5)
var a = Vector2(2, 5)
# create a vector and assign x and y manually
var b = Vector2()
b.x = 3
b.y = 1
// create a vector with coordinates (2, 5)
var a = new Vector2(2, 5);
// create a vector and assign x and y manually
var b = new Vector2();
b.x = 3;
b.y = 1;
벡터의 합¶
두 벡터를 더하거나 뺼 떄, 해당하는 구성요소는 더해집니다:
var c = a + b # (2, 5) + (3, 1) = (5, 6)
var c = a + b; // (2, 5) + (3, 1) = (5, 6)
첫번째 벡터의 끝에 두번째 벡터를 더함으로써 우리는 시각적으로도 이것을 확인할 수 있습니다:

즉 더하기 a+b는 b+a 와 같은 결과 값을 갖는다.
스칼라 곱¶
참고
벡터는 방향과 크기 둘 다를 나타냅니다. 크기만 나타내고 있는 값을 **스칼라**라고 합니다.
벡터는 스칼라에 의해 곱해질 수 있습니다:
var c = a * 2 # (2, 5) * 2 = (4, 10)
var d = b / 3 # (3, 6) / 3 = (1, 2)
var c = a * 2; // (2, 5) * 2 = (4, 10)
var d = b / 3; // (3, 6) / 3 = (1, 2)

참고
벡터에 스칼라를 곱하는 것은 벡터의 방향을 바꾸지는 않고, 이것의 크기만 바꿉니다. 이것이 바로 벡터의 크기를 조정하는 방법입니다.
실용적인 응용¶
벡터 덧셈과 뺄셈의 두 가지 일반적인 용법을 살펴보자.
이동¶
벡터는 크기와 방향을 가진 모든 양을 나타낼 수 있습니다. 대표적인 예로는 위치, 속도, 가속도, 힘이 있습니다. 이 그림에서 1단계의 우주선은 위치 벡터 (1,3)
과 속도 벡터 (2,1)
을 가지고 있습니다. 속도 벡터는 배가 각 단계마다 이동하는 정도를 나타냅니다. 현재 위치에 속도를 더함으로써 2단계의 위치를 찾을 수 있습니다.

팁
속도는 시간 단위당 위치의 변화를 측정합니다. 새로운 위치는 이전 위치에 속도를 더함으로써 찾을 수 있습니다.
표적을 향하기¶
이 시나리오에서, 당신은 회전 포탑을 로봇에게 겨누고자 하는 탱크를 가지고 있습니다. 로봇의 위치에서 탱크의 위치를 빼면 탱크에서 로봇을 가리키는 벡터를 얻을 수 있습니다.

팁
"A"에서 "B"로 향하는 벡터를 찾으려면 "B - A"를 사용합니다.
단위 벡터¶
크기 가 1인 벡터를 단위 벡터 라고 합니다. 또한 이러한 벡터는 방향 벡터 또는 법선벡터 라고도 합니다. 단위 벡터는 방향을 추적해야 할 때 유용합니다.
표준화¶
Normalizing a vector means reducing its length to 1
while
preserving its direction. This is done by dividing each of its components
by its magnitude. Because this is such a common operation,
Vector2
and Vector3
provide a method for normalizing:
a = a.normalized()
a = a.Normalized();
경고
표준화는 벡터 길이로 나누어지기 때문에 길이 "0"의 벡터를 표준화할 수 없습니다. 이렇게 시도한다면 오류가 발생할 것입니다.
반사¶
단위벡터의 일반적인 용도는 법선 벡터 를 나타내는 것입니다. 법선 벡터는 표면에 수직으로 정렬된 단위 벡터를 말하며, 방향을 정의합니다. 이 장치는 일반적으로 조명, 콜리전 및 표면과 관련된 기타 작업에 사용됩니다.
예를 들어, 우리가 벽이나 다른 물체에서 튀기길 원하는 움직이는 공을 가지고 있다고 상상해 보세요:

이 표면은 수평면이기 때문에 표면 법선벡터 값은 (0, -1)
입니다. 공이 충돌할 때, 우리는 그것의 남은 운동(표면에 부딪힐 때 남은 양)을 취하고 이것을 법선벡터를 이용해 반사시킵니다. Godot에서 :ref :vector2 <class_Vector2> 클래스는 이것을 다루는 bounce()
메서드를 가지고 있습니다. 위 다이어그램의 KinemicalBody2D를 이용하는 GDScript 예제입니다:
# object "collision" contains information about the collision
var collision = move_and_collide(velocity * delta)
if collision:
var reflect = collision.remainder.bounce(collision.normal)
velocity = velocity.bounce(collision.normal)
move_and_collide(reflect)
// KinematicCollision2D contains information about the collision
KinematicCollision2D collision = MoveAndCollide(_velocity * delta);
if (collision != null)
{
var reflect = collision.Remainder.Bounce(collision.Normal);
_velocity = _velocity.Bounce(collision.Normal);
MoveAndCollide(reflect);
}
내적¶
내적은 벡터 수학에서 가장 중요한 개념 중 하나이지만 종종 잘못 이해됩니다. 내적은 두 벡터를 스칼라 로 반환해주는 연산입니다. 크기와 방향 모두를 포함하는 벡터와는 다르게 스칼라 값은 오직 크기만 갖습니다.
내적의 공식은 두가지 형태를 취한다:

그리고

그러나, 대부분의 경우 내장된 메서드를 사용하는 것이 가장 쉽습니다. 두 벡터의 순서는 중요하지 않습니다:
var c = a.dot(b)
var d = b.dot(a) # These are equivalent.
float c = a.Dot(b);
float d = b.Dot(a); // These are equivalent.
The dot product is most useful when used with unit vectors, making the
first formula reduce to just cosθ
. This means we can use the dot
product to tell us something about the angle between two vectors:

단위벡터를 사용할때, 결과는 항상 -1(180°)에서 1(0°) 사이일 것이다.
직면¶
우리는 이 사실을 어떤 물체가 다른 물체를 향하고 있는지 감지하는 데 이용할 수 있습니다. 아래 그림에서 P
선수는 좀비 A
와 B
를 피하려고 합니다. 좀비의 시야가 180°라고 가정하면 플레이어를 볼 수 있을까요?

녹색 화살표 fA
와 fB
는 좀비들이 마주보는 방향을 나타내는 단위 벡터이고 파란 반원형은 좀비의 시야를 나타냅니다. 좀비 A
의 경우 P - A
값을 정규화해 만든 방향 벡터인 AP
가 보입니다. Godot은 direction_to
라고 부르는 도우미 메소드를 가지고 있습니다. 만약 이 벡터와 마주보는 벡터 사이의 각도가 90° 미만일 경우 좀비는 플레이어를 볼 수 있습니다.
코드에서는 이렇게 보일 것이다:
var AP = A.direction_to(P)
if AP.dot(fA) > 0:
print("A sees P!")
var AP = A.DirectionTo(P);
if (AP.Dot(fA) > 0)
{
GD.Print("A sees P!");
}
외적¶
Like the dot product, the cross product is an operation on two vectors. However, the result of the cross product is a vector with a direction that is perpendicular to both. Its magnitude depends on their relative angle. If two vectors are parallel, the result of their cross product will be a null vector.


외적은 이렇게 계산된다:
var c = Vector3()
c.x = (a.y * b.z) - (a.z * b.y)
c.y = (a.z * b.x) - (a.x * b.z)
c.z = (a.x * b.y) - (a.y * b.x)
var c = new Vector3();
c.x = (a.y * b.z) - (a.z * b.y);
c.y = (a.z * b.x) - (a.x * b.z);
c.z = (a.x * b.y) - (a.y * b.x);
고도에서는, 기본 방법을 사용할 수 있습니다:
var c = a.cross(b)
var c = a.Cross(b);
참고
외적에서는, 순서가 중요합니다. "a.cross(b)"는 "b.cross(a)"와 같은 결가가 나오지 않습니다. 결과 벡터는 반대쪽 방향을 가리킵니다.
법선 계산하기¶
외적의 일반적인 용도는 3D 공간에서 표면 또는 평명의 법선 표면을 찾는 것입니다. 삼각형 "ABC"가 있다면 벡터 뺄셈을 사용하여 "AB"와 "AC"의 두 모서리를 찾을 수 있습니다. 외적을 이용하여 "AB x AC"는 두 가지 모두에 수직인 벡터를 생성합니다: 표면에 수직방향.
이것은 삼각형에 수직인 평면을 계산하는 함수이다:
func get_triangle_normal(a, b, c):
# find the surface normal given 3 vertices
var side1 = b - a
var side2 = c - a
var normal = side1.cross(side2)
return normal
Vector3 GetTriangleNormal(Vector3 a, Vector3 b, Vector3 c)
{
// find the surface normal given 3 vertices
var side1 = b - a;
var side2 = c - a;
var normal = side1.Cross(side2);
return normal;
}
대상 가리키기¶
위의 내적 섹션에서, 우리는 두 벡터 사이의 각도를 찾는 데 어떻게 이것을 이용할 수 있는지 확인했습니다. 그러나 3차원에서는 정보가 충분하지 않습니다. 우리는 또한 어떤 축을 중심으로 회전해야 하는지 알아야 합니다. 우리는 현재 마주보는 방향과 목표 방향의 외적을 계산함으로써 그것을 발견할 수 있습니다. 그 결과인 수직 벡터는 회전의 축입니다.
더 많은 정보¶
고도에서 벡터 수학을 이용하는 것에 대해 더 많은 정보를 원한다면, 다음 글들을 봐주십시오: