Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

벡터 수학

소개

이 튜토리얼은 게임 개발에 적용되는 선형대수에 대한 짧고 실용적인 소개입니다. 선형 대수란 벡터와 벡터 사용에 대한 학문입니다. 벡터는 2D 및 3D 개발 모두에서 많은 응용방법이 있으며 Godot는 이를 광범위하게 사용합니다. 벡터 수학에 대한 올바른 이해는 강력한 게임 개발자가 되기 위해 필수적입니다.

참고

이 튜토리얼은 선형대수에 관한 공식 교과서가 절대 아닙니다. 우리는 단지 그것이 어떻게 게임 개발에 적용되는지 지켜볼 것입니다. 수학에 대한 자세한 내용은 https://www.khanacademy.org/math/linear-algebra을 참조하세요

좌표계 (2D)

2차원 공간에서, 좌표계들은 가로축(x)과 세로축(y)을 사용하여 정의됩니다. 2차원 공간에서의 특정한 위치는 (4,3)과 같이 한 쌍의 값으로 쓰여집니다.

../../_images/vector_axis1.png

참고

컴퓨터 그래픽을 처음 접하는 사람이라면 아마 수학 수업에서 배웠듯이 양의``y``축이 위쪽이 아니라 아래쪽을 가리키는 것이 이상하게 보일지도 모릅니다. 그러나 대부분의 컴퓨터 그래픽 응용 프로그램에서는 일반적으로 이러한 현상이 발생합니다.

2D 평면의 모든 위치는 이러한 방식으로 한 쌍의 수들로 식별할 수 있습니다. 그러나 우리는 또한 (4, 3)의 위치를 (0, 0)또는 원점으로부터의 오프셋으로 생각할 수 있습니다. 원점에서 점까지 점을 가리키는 화살표를 그리세요:

../../_images/vector_xy1.png

이것은 벡터입니다. 벡터는 유용한 많은 정보들을 보여줍니다. 점이 (4, 3)에 있다고 알려줄 뿐 아니라, 우리는 각도 θ (세타) 그리고 길이 (또는 크기) m 또한 생각해낼 수 있습니다. 이러한 경우 화살표는 위치 벡터로, 원점에 상대적인 공간의 위치를 나타냅니다.

벡터에 대해 고려해야 할 매우 중요한 점은 벡터가 상대적인 방향과 크기만 나타낸다는 것입니다. 벡터의 위치에 대한 개념이 없습니다. 다음 두 벡터는 동일합니다:

../../_images/vector_xy2.png

두 벡터 모두 시작점으로부터 오른쪽으로 4만큼 아래쪽으로 3만큼의 단위를 나타냅니다. 평면에서 벡터를 그리는 것은 중요하지 않습니다. 이것은 항상 상대적인 방향과 크기를 나타냅니다.

벡터 연산

당신은 둘 중 하나의 방법(x 및 y 좌표 또는 각도 및 크기)을 사용하여 벡터를 참조할 수 있지만, 프로그래머는 편의를 위해 일반적으로 좌표 표기법을 사용합니다. 예를 들어, Godot에서 원점은 화면의 왼쪽 상단 모서리이고, Node2D라는 2차원의 노드를 400픽셀 오른쪽, 300픽셀 아래로 배치하려면 다음 코드를 사용하세요:

$Node2D.position = Vector2(400, 300)

Godot는 2D 및 3D 사용 시 각각 :ref: Vector2 <class_Vector2>와 :ref:`Vector3 <class_Vector3>를 지원합니다. 이 문서에서 논의된 동일한 수학적 규칙은 두 가지 유형 모두에 적용됩니다.

멤버 접근

벡터의 각각의 컴포넌트는 이름으로 직접 접근할 수 있습니다.

# 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

벡터의 합

두 벡터를 더하거나 뺄 때, 해당하는 컴포넌트는 더해집니다:

var c = a + b  # (2, 5) + (3, 1) = (5, 6)

첫번째 벡터의 끝에 두번째 벡터를 더함으로써 우리는 시각적으로도 이것을 확인할 수 있습니다:

../../_images/vector_add1.png

a + b를 더하는 것은 b + a를 더하는 것과 같은 결과를 가져온다는 점을 참고하세요.

스칼라 곱

참고

벡터는 방향과 크기 둘 다를 나타냅니다. 크기만 나타내고 있는 값을 스칼라라고 합니다. 스칼라는 Godot에서 float 유형을 사용합니다.

벡터는 스칼라에 의해 곱해질 수 있습니다:

var c = a * 2  # (2, 5) * 2 = (4, 10)
var d = b / 3  # (3, 6) / 3 = (1, 2)
var e = d * -2 # (1, 2) * -2 = (-2, -4)
../../_images/vector_mult1.png

참고

벡터에 스칼라를 곱하는 것은 벡터의 방향을 바꾸지는 않고, 이것의 크기만 바꿉니다. 이것이 바로 벡터의 크기를 조절하는 방법입니다.

실용적인 응용

벡터 덧셈과 뺄셈의 두 가지 일반적인 용법을 살펴보자.

이동

벡터는 크기와 방향을 가진 모든 양을 나타낼 수 있습니다. 대표적인 예로는 위치, 속도, 가속도, 힘이 있습니다. 이 이미지에서 1단계의 우주선은 위치 벡터 (1,3)과 속도 벡터 (2,1)을 가지고 있습니다. 속도 벡터는 배가 각 단계마다 이동하는 정도를 나타냅니다. 현재 위치에 속도를 더함으로써 2단계의 위치를 찾을 수 있습니다.

../../_images/vector_movement1.png

속도는 시간 단위당 위치의 변화를 측정합니다. 새로운 위치는 이전 위치에 속도를 더함으로써 찾을 수 있습니다.

일반적인 2D 게임 시나리오에서는 초당 픽셀 단위의 속도를 갖고 이를 _process() 또는 _physics_process() 콜백의 delta 매개변수(이전 프레임 이후 경과된 시간)로 곱합니다.

표적을 향하기

이 시나리오에서, 당신은 회전 포탑을 로봇에게 겨누고자 하는 탱크를 가지고 있습니다. 로봇의 위치에서 탱크의 위치를 빼면 탱크에서 로봇을 가리키는 벡터를 얻을 수 있습니다.

../../_images/vector_subtract2.webp

"A"에서 "B"로 향하는 벡터를 찾으려면 "B - A"를 사용합니다.

단위 벡터

크기 가 1인 벡터를 단위 벡터 라고 합니다. 또한 이러한 벡터는 방향 벡터 또는 법선벡터 라고도 합니다. 단위 벡터는 방향을 추적해야 할 때 유용합니다.

표준화

벡터를 표준화 한다는 것의 의미는 벡터의 방향은 유지하면서 벡터의 길이를 1로 줄이는 것입니다. 이것은 각 벡터를 그것의 크기로 나누면서 이루어집니다:

a = a.normalized()

경고

표준화는 벡터 길이로 나누어지기 때문에 길이 "0"의 벡터를 표준화할 수 없습니다. 이렇게 시도한다면 오류가 발생할 것입니다.

반사

단위벡터의 일반적인 용도는 법선 벡터 를 나타내는 것입니다. 법선 벡터는 표면에 수직으로 정렬된 단위 벡터를 말하며, 방향을 정의합니다. 이 장치는 일반적으로 조명, 콜리전 및 표면과 관련된 기타 작업에 사용됩니다.

예를 들어, 우리가 벽이나 다른 물체에서 튀기길 원하는 움직이는 공을 가지고 있다고 상상해 보세요:

../../_images/vector_reflect1.png

이 표면은 수평면이기 때문에 표면 법선벡터 값은 (0, -1)입니다. 공이 충돌할 때, 우리는 그것의 남은 운동(표면에 부딪힐 때 남은 양)을 취하고 이것을 법선벡터를 이용해 반사시킵니다. Godot에서 :ref :vector2 <class_Vector2> 클래스는 이것을 다루는 bounce() 메서드를 가지고 있습니다. 위 다이어그램의 KinemicalBody2D를 이용하는 GDScript 예제입니다:

var collision: KinematicCollision2D = move_and_collide(velocity * delta)
if collision:
    var reflect = collision.get_remainder().bounce(collision.get_normal())
    velocity = velocity.bounce(collision.get_normal())
    move_and_collide(reflect)

내적

내적은 벡터 수학에서 가장 중요한 개념 중 하나이지만 종종 잘못 이해됩니다. 내적은 두 벡터를 스칼라 로 반환해주는 연산입니다. 크기와 방향 모두를 포함하는 벡터와는 다르게 스칼라 값은 오직 크기만 갖습니다.

내적의 공식은 두가지 형태를 취한다:

../../_images/vector_dot1.png

그리고

../../_images/vector_dot2.png

수학적 표기법 ||A||*는 벡터 ``A``의 크기를 나타내고, *Ax`는 벡터 ``A``의 ``x` 구성 요소를 의미합니다.

그러나, 대부분의 경우 내장된 메서드를 사용하는 것이 가장 쉽습니다. 두 벡터의 순서는 중요하지 않습니다:

var c = a.dot(b)
var d = b.dot(a)  # These are equivalent.

내적은 첫 번째 공식을 cosθ로 줄이므로 단위 벡터와 함께 사용할 때 가장 유용합니다. 즉, 내적을 사용하면 두 벡터 사이의 각도에 대해 설명할 수 있습니다:

../../_images/vector_dot3.png

단위벡터를 사용할때, 결과는 항상 -1(180°)에서 1(0°) 사이일 것이다.

직면

우리는 이 사실을 어떤 물체가 다른 물체를 향하고 있는지 감지하는 데 이용할 수 있습니다. 아래 그림에서 P 선수는 좀비 AB를 피하려고 합니다. 좀비의 시야각이 180°라고 가정하면 플레이어를 볼 수 있을까요?

../../_images/vector_facing2.png

녹색 화살표 fAfB는 좀비들이 마주보는 방향을 나타내는 단위 벡터이고 파란 반원형은 좀비의 시야를 나타냅니다. 좀비 A의 경우 P - A값을 정규화해 만든 방향 벡터인 AP가 보입니다. Godot는 direction_to라고 부르는 도우미 메서드를 가지고 있습니다. 만약 이 벡터와 마주보는 벡터 사이의 각도가 90° 미만일 경우 좀비는 플레이어를 볼 수 있습니다.

코드에서는 이렇게 보일 것이다:

var AP = A.direction_to(P)
if AP.dot(fA) > 0:
    print("A sees P!")

외적

내적과 같이, 외적은 두 벡터사이의 연산입니다. 그러나 외적의 결과는 양쪽과 수직의 방향을 가진 벡터입니다. 그것의 크기는 그것들의 상대적인 각도에 의존합니다. 만약 두 벡터가 평행이라면, 외적의 결과는 0벡터일 것입니다.

../../_images/vector_cross1.png ../../_images/vector_cross2.png

외적은 이렇게 계산된다:

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)

Godot에서는 내장 Vector3.cross() 메서드를 사용할 수 있습니다:

var c = a.cross(b)

외적은 2D에서 수학적으로 정의되지 않습니다. Vector2.cross() 메서드는 2D 벡터에 대한 3D 외적의 일반적으로 사용되는 아날로그입니다.

참고

외적에서는, 순서가 중요합니다. 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

대상 가리키기

위의 내적 섹션에서, 우리는 두 벡터 사이의 각도를 찾는 데 어떻게 이것을 이용할 수 있는지 확인했습니다. 그러나 3차원에서는 정보가 충분하지 않습니다. 우리는 또한 어떤 축을 중심으로 회전해야 하는지 알아야 합니다. 우리는 현재 마주보는 방향과 목표 방향의 외적을 계산함으로써 그것을 발견할 수 있습니다. 그 결과인 수직 벡터는 회전의 축입니다.

추가 정보

Godot에서 벡터 수학을 사용하는 것에 대한 자세한 정보는 다음 기사를 참조하세요: