숏컷 코드
heading = target - current
direction = normalize(heading)
speedVector = direction * speed문법과 예시
벡터는 위치가 아니라 방향과 크기다
점(point)은 "어디에 있는가"를 나타내고 벡터는 "얼마나, 어느 방향으로"를 나타냅니다. 두 점을 빼면 방향과 거리 정보가 담긴 벡터가 됩니다. 이 구분이 없으면 "목표 위치 - 현재 위치"가 이동 방향이 되는 이유를 이해하지 못하고, 위치 벡터와 방향 벡터를 잘못 섞어 쓰는 버그가 생깁니다. 스칼라(크기만 있는 값)와 벡터(크기 + 방향)의 차이도 중요합니다. 거리, 체력, 시간은 스칼라이고 속도, 힘, 이동 방향은 벡터입니다. 이 구분을 먼저 잡으면 물리 공식을 읽을 때 의미가 살아납니다.
directionVec = targetPos - currentPos // 벡터: 방향 + 크기(거리)
distance = magnitude(directionVec) // 스칼라: 크기만
direction = normalize(directionVec) // 벡터: 방향만, 크기는 1
velocity = direction * speed // 벡터: 방향 * 스칼라정규화는 방향을 보존하고 길이를 버린다
정규화(normalization)는 벡터의 방향은 유지하면서 길이를 1로 맞추는 연산입니다. 정규화된 벡터를 단위 벡터(unit vector)라고 부릅니다. 방향 비교나 이동 방향 계산에서 거리 정보가 영향을 주지 않게 하려면 정규화가 필요합니다. 반대로 거리가 중요한 계산(감쇠, 범위 판정)에서 정규화하면 길이 정보가 사라져 틀린 결과가 나옵니다. 또 영벡터(길이가 0인 벡터)를 정규화하면 나눗셈 오류가 발생하므로, 정규화 전 길이가 0인지 확인하는 방어 코드가 필요합니다.
// 방어 코드 예시
if (heading.magnitude > 0.001f)
direction = heading.normalized
else
direction = Vector3.zero // 정지 상태dot product는 두 방향이 얼마나 같은 쪽을 보는지 수치화한다
dot(a, b) = |a| * |b| * cos(θ)에서 두 벡터가 단위 벡터라면 결과는 cos(θ)만 남습니다. 결과가 1이면 같은 방향, 0이면 직각, -1이면 반대 방향입니다. 이를 이용해 시야각 판정, 정면/후면 구분, 입력 방향과 이동 방향의 일치도, 램버트 조명(표면 normal과 빛 방향의 dot)을 계산합니다. 비용이 낮고 직관적이기 때문에 "두 방향 관계"가 필요한 대부분의 게임 로직에 dot을 먼저 검토하는 것이 실용적입니다. 단, dot 결과를 각도처럼 바로 읽지 말고 항상 단위 벡터 기준의 코사인 값임을 기억해야 합니다.
// 적이 플레이어를 시야 내에서 보는지 판정
toPlayer = normalize(playerPos - enemyPos)
facingScore = dot(enemyForward, toPlayer) // -1 ~ 1
isInFOV = facingScore > cos(fovAngle / 2) // 60도 시야 = cos(30°) ≈ 0.866cross product는 두 벡터에 수직인 축을 만든다
cross(a, b)는 두 벡터 모두에 수직인 새로운 벡터를 만듭니다. 3D에서 표면 normal 계산, 오른쪽 벡터 생성, 회전 축 결정에 사용합니다. 중요한 것은 순서입니다. cross(a, b)와 cross(b, a)는 방향이 반대입니다. 오른손 좌표계(OpenGL)와 왼손 좌표계(DirectX 기본)에서 결과 방향이 다를 수 있습니다. "왼쪽인지 오른쪽인지" 방향 판정에도 쓰입니다. cross 결과의 부호(y 성분 등)를 확인해 상대 위치가 어느 쪽에 있는지 알 수 있습니다.
// 표면 normal 계산
normal = normalize(cross(edge1, edge2))
// 오른쪽 벡터 계산
right = normalize(cross(forward, worldUp))
// 왼쪽/오른쪽 판정
side = cross(myForward, toTarget).y
isToLeft = side < 0벡터 연산을 고를 때 핵심
| 상황 | 적합한 선택 |
|---|---|
| 이동 방향 계산 | 두 점의 차 벡터 후 정규화 |
| 시야각 판정, 정면/후면 구분 | 단위 벡터끼리 dot |
| 거리 기반 감쇠, 범위 판정 | 정규화하지 말고 magnitude 사용 |
| 표면 normal, 오른쪽 벡터 | cross |
| 왼쪽/오른쪽 방향 판정 | cross 결과 부호 확인 |
| 대각선 이동 속도 보정 | 입력 벡터를 정규화한 뒤 속도 곱하기 |
특이 케이스와 주의할 점
흔한 실패는 방향 입력 (1, 1)을 그대로 속도에 곱해 대각선 이동이 직선보다 빨라지는 경우입니다. 방향이 목적이면 먼저
정규화하고, 거리나 세기를 보존해야 할 때만 길이를 남기세요. 또 dot은 각도가 아니라 코사인 값이고, 영벡터 정규화는
NaN을 만들 수 있다는 점도 항상 같이 체크해야 합니다.
참고 링크
2 sources