본문 바로가기
개발/Unity

[Unity] 벡터의 내적과 외적

by 남생이야 2024. 4. 30.

벡터란? 

  크기와 방향을 가지는 물리적 양을 말한다. 사실 실제로는 방향만 가지고 있다.

 

  • 벡터 + 벡터 = 그 만큼 이동한 위치를 나타낸다. 
  • 벡터1 - 벡터2 = 벡터2가 벡터1을 바라 보는 방향을 나타낸다.

 

파란선으로 나타낸 초록색 큐브(벡터) - 흰 큐브(벡터)의 결과

 

위 코드에서 정규화(normalized)를 하여 계산에 추가

 

방향 벡터의 길이는 거리다. 그러나 방향 벡터는 정규화하여 사용한다.

정규화를 통해 거리값을 곱하는 것만으로 쉽게 결과를 얻을 수 있다.

 

 

벡터의 내적 (Dot Product) 

  •  벡터의 내적은 벡터를 수처럼 곱하는 개념이다.
  •  두 방향 벡터의 내각을 구할 수 있다. 게임에선 각도의 개념은 우리가 일상에서 사용하는 60분법을 사용하지 않는다. 특정 대상을 기준으로 왼쪽인지 오른쪽인지를 구하기 쉽게 하기 위해 사용한다. (호도법 = 라디안) 

 

수식 

(A.x*B.x+A.y*B.y+A.z*B.z) = |A||B|cos(theta)

 

 

특정 대상 물체 뒤(180도)에 갈수록 -1에 가까워 진다.

 

벡터의 외적 (Cross Product) 

  • 벡터의 내적은 좌우를 구분 지을 수 없다는 문제가 있다. 이를 해결하기 위해 벡터의 외적이라는 개념을 사용한다. 
  •  벡터의 외적의 결과는 방향이 나타난다. 
  • Unity 기준  Z축 평행 방향으로 녹색 큐브를  축이동해도 흰색 큐브의 Y축(녹색선) 의 길이는 항상 일치한다. 

녹색 큐브를 흰색 큐브 왼쪽으로 이동하면 녹색 기즈모선은 흰색 큐브 아래로 나타난다.

 

 

 Vector3 cross = Vector3.Cross(transform.forward, direction);
 float distance = Vector3.Dot(cross, Vector3.up); // <- y값 추출하기 외적에 내적을 추출하면 평행간에 거리가 나온다

 

  두 큐브의 전방(Z축) 기준으로 외적을 구한 값을 다시 내적을 하고 난 결과 값은 두 벡터의 평행한 z축의 거리 값을 알 수 있 다. 

 

 

 

etc.

벡터의 내적과 외적을 동시에 쓰는면  60분법각을 구할 때 사용할 수 있다. 

 

전체 코드 

using UnityEngine;

public class Test_Vector : MonoBehaviour
{
    [SerializeField]
    private GameObject cube2;

    private Vector3 result; 


    private void Start ()
    {
        //transform.position = transform.position + new Vector3(2, 0, 3);
    }

    private void Update()
    {
        Vector3 position = transform.position;
        Vector3 position2 = cube2.transform.position;

        result = position2 - position;
    }

    [SerializeField]
    private float distance = 5.0f;

    private float dot;
    private Vector3 cross; 

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawLine(transform.position, transform.position + transform.forward * distance);


        Vector3 from = transform.position;
        Vector3 to = result;

        Gizmos.color = Color.blue;
        //Gizmos.DrawLine(from, from + to);

        Vector3 normal = result.normalized;
        Gizmos.DrawLine(from, from + normal * 5.0f);

        dot = Vector3.Dot(transform.forward, result.normalized);

        Gizmos.color = Color.green;
        cross = Vector3.Cross(transform.forward, result);
        Gizmos.DrawLine(transform.position, transform.position + cross);
    }

    private void OnGUI()
    {
        GUI.color = Color.red;
        GUILayout.Label(dot.ToString());
        GUILayout.Label(cross.ToString());

        float y = Vector3.Dot(cross, Vector3.up);   // y값만 가져올 수 있다. 모든항을 곱하고 더하니 특정 값만 가져올 수 있음
        GUILayout.Label(y.ToString());

        float sign = Mathf.Sign(y); // 0보다 작으면 -1 
        GUILayout.Label(sign.ToString());
    }
}

'개발 > Unity' 카테고리의 다른 글

Monster Pattern 0508 작업  (0) 2024.05.08
몬스터 패턴 작업  (0) 2024.05.07
프리팹(Prefab)  (0) 2024.04.27
레거시 / 휴머노이드 애니메이션 차이  (0) 2024.04.26
[Unity] Transform 기초  (0) 2024.04.16