[게임수학] 6-2. 투영 벡터

2025. 9. 12. 20:03·게임수학
728x90

→ 이 글은 「이득우의 게임 수학」을 바탕으로 작성했습니다.

■ 투영 벡터

벡터의 투영은 벡터 $\vec v$를 다른 벡터 $\vec w$의 방향으로 내려놓는 것을 의미한다.

 

따라서 투영 벡터의 방향은 $\vec w$와 같고, 그 크기는 $\vec v$와 $\vec w$의 내적(각도와 두 벡터의 길이에 따라 결정)에 의해 달라진다.

[투영 벡터 구하기 - 1]

투영할 벡터를 $\vec v$, 투영의 기준이 되는 벡터를 $\vec w$라 해보자.

 

벡터 $\vec v$를 $\vec w$의 방향으로 수직으로 내리면, $\vec w$가 만드는 직선 위에 수선의 발이 생긴다. 이 점을 원점과 연결한 벡터가 바로 투영 벡터$(\vec t)$이다.

 

[투영 벡터 구하기 - 2]

투영한 벡터의 크기$(|\vec t|)$를 알고 있다면, 우리는 기준 벡터 $(|\vec w|)$를 정규화시킨 벡터$(\hat w = \frac{\vec w}{|\vec w|})$를 곱해 투영된 벡터를 얻어낼 수 있다.

$$ \vec t = |\vec t| \cdot \hat w $$

위 수식에서 내적을 활용해 $\vec v$로부터 $\vec t$를 구하도록 수식을 전개해보자.

 

1. 단위 벡터 구하기

$$ |\vec t| \cdot \frac{\vec w}{|\vec w|} $$

$\vec w$의 단위 벡터를 구하기 위해 벡터를 크기로 나누어 정규화한다.

 

2. $\vec t$의 크기 구하기

$$ |\vec v|\cdot \cos\theta \cdot \frac{\vec w}{|\vec w|} $$

$\vec v$에서 수선의 발을 내려 직각삼각형을 만들면, 원점에서 수선의 발까지의 거리는 $|\vec v|\cos\theta$로 표현할 수 있다.

 

3. 내적 공식 활용

$$ \vec v \cdot \vec w = |\vec v||\vec w|\cos\theta $$

앞서 우리가 배웠던 내적 공식에서 $\cos\theta$를 구하기 위해 양 변을 $|\vec v||\vec w|$로 나누면,

$$ \cos\theta = \frac{\vec v\cdot \vec w}{|\vec v||\vec w|} $$

위와 같이 정리가 된다. 이 식을 2의 수식에 대입하면 아래와 같이 정리가 가능하다.

$$ |\vec v| \cdot \frac{\vec v\cdot \vec w}{|\vec v||\vec w|} \cdot \frac{\vec w}{|\vec w|} $$

 

4. 최종 정리

$$ \vec t = \frac{\vec v\cdot \vec w}{(\vec w\cdot \vec w)}\cdot \vec w $$

분자와 분모를 소거하고 정리한 뒤, 벡터 크기의 제곱을 내적으로 표현하면 위와 같이 정리된다. 여기서 투영할 기준이 되는 벡터$\vec w$의 크기가 1이라면 아래와 같이 단순하게 정리된다.

$$ \vec t = (\vec v\cdot \vec w)\cdot \vec w $$

 

 

■ 투영 벡터의 응용

[투영 벡터의 응용]

$$ \vec u = \vec v - \vec t $$

우리가 구한 투영 벡터$(\vec t)$에서 투영할 벡터$(\vec v)$의 성분을 제외하면, 기준이 되는 벡터$(\vec w)$와 수직인 벡터가 생성된다.

  • $\vec w$와 $\vec t$의 내적 결과 역시 0이 되므로 수직이 되는 것을 알 수 있다.

일반적인 벡터 $\vec v - \vec t$의 차는 단순히 “$\vec v$에서 $\vec t$로 가는 벡터”지만, $\vec t$가 $\vec v$를 어떤 방향으로 투영한 결과라면 얘기가 달라진다.

 

즉,

$$ \vec t = \mathrm{proj}_{\vec w}(\vec v) $$

이라면, $\vec v - \vec t$는 $\vec v$에서 $\vec w$방향 성분$\vec t$를 제외한 나머지, 곧 $\vec w$에 수직인 성분이 된다.

 

[경사로 이동 방향 구하기]

투영 벡터를 사용하면 “경사로에서의 플레이어의 이동 방향”을 계산할 수 있다.

  • 투영할 벡터 : 플레이어의 정면
  • 기준 벡터 : 평면의 노말
  • 이동 방향 : 플레이어의 정면 벡터 - 투영된 벡터
public class ProjectionPlayer : MonoBehaviour
{
    [SerializeField] private float speed = 20f;
    [SerializeField] private Transform rayTransform;
    [SerializeField] private LayerMask groundLayer;
    private void Update()
    {
        var ray = new Ray(rayTransform.position, Vector3.down);

        if (Physics.Raycast(ray, out var hit, 100f, groundLayer) == false)
        {
            return;
        }

        // 투영할 벡터(플레이어의 정면)      
        var forward = transform.forward.normalized;
        // 기준 벡터(평면의 normal)
        var normal = hit.normal;

        // 투영된 벡터
        var projection = Vector3.Dot(forward, normal) * normal;
        // 평면의 normal과 수직인 벡터
        var dir = forward - projection;

        var input = Input.GetAxis("Horizontal");
        transform.Translate(dir * speed * input * Time.deltaTime, Space.World);
        
        // debug
        Debug.DrawRay(rayTransform.position, projection, Color.red);
        Debug.DrawRay(rayTransform.position, dir, Color.green);
    }
}

[경사로 이동]

앞서 배웠던 $\vec p = (\vec f\cdot \vec n)\vec n$ 공식을 사용하여 투영 벡터를 구한다.

 

이후, 원래의 벡터($\vec f :$ 플레이어 정면)에서 투영된 벡터의 성분을 빼면, 평면의 노말$\vec n$과 직교하는 벡터 $(\vec d = \vec f - \vec p)$를 얻을 수 있다.

// 투영할 벡터(플레이어의 정면)      
var forward = transform.forward.normalized;
// 기준 벡터(평면의 normal)
var normal = hit.normal;
// 함수 사용
var dir = Vector3.ProjectOnPlane(forward, normal);

Unity에서는 Vector3.ProjectOnPlane(Vector3 vector, Vector3 planeNormal) 함수를 제공한다.

 

이 함수는 지정한 벡터에서 특정 평면의 노말 방향 성분을 제거하고, 평면 위에 남는 성분을 반환한다.

 

따라서 transform.forward를 평면 위로 투영하면, 플레이어가 경사면 위에서 실제로 이동할 수 있는 방향을 손쉽게 구할 수 있다.

728x90

'게임수학' 카테고리의 다른 글

[게임수학] 6-1. 내적(Dot product)  (0) 2025.09.12
[게임수학] 5.아핀공간  (1) 2025.09.08
[게임수학] 4. 행렬  (1) 2025.09.05
[게임수학] 3. 삼각함수  (2) 2025.08.31
[게임수학] 2. 벡터(Vector)  (2) 2025.08.27
'게임수학' 카테고리의 다른 글
  • [게임수학] 6-1. 내적(Dot product)
  • [게임수학] 5.아핀공간
  • [게임수학] 4. 행렬
  • [게임수학] 3. 삼각함수
브라더스톤
브라더스톤
유티니, C#과 관련한 여러 정보를 끄적여둔 블로그입니다. Email : dkavmdk98@gmail.com
  • 브라더스톤
    젊은 프로그래머의 슬픔
    브라더스톤
  • 전체
    오늘
    어제
    • 개발 노트 (34) N
      • Unity,C# (27)
        • Unity 정보 (5)
        • 알고리즘 (11)
        • 자료구조 (2)
        • 절차적생성(PCG) (9)
      • 게임수학 (7) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    절차적던전생성
    ProjectOnPlane
    알고리즘
    정렬알고리즘
    게임수학
    BSP
    앞뒤판별
    unity
    기저벡터
    이동변환
    경사로이동
    PerlinNoise
    시야판별
    절차적지형생성
    자료구조
    pcg
    이진공간분할
    아핀공간
    최단경로찾기
    C#
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
브라더스톤
[게임수학] 6-2. 투영 벡터
상단으로

티스토리툴바