프로그래밍/Unity

[Unity] 벡터의 내적 Vector2D, Vector3D

Lou Park 2021. 12. 18. 16:44

벡터는 크기(Magnitude)와 방향(Direction)을 표현하는 값으로, 주로 화살표를 통해 나타낸다. 그림에서의 벡터는 원점에서 부터 P2(12, 5)로 방향성을 띄고 있으며, 백터의 크기는 피타고라스 정리를 통해 계산하면 13이된다.

Vector2 v1 = new Vector2(12, 5);
Debug.Log(v1.magnitude); // 13

 

움직이는 물체는 그 속력(Velocity)이 있는데, 이 속도 역시 벡터로 표현 가능하다. Fredrick은 현재 (5, 6)에 위치해있고, 1시간에 (12, 5)만큼 이동하는 속력를 가지고 있을때, Fredrict의 1시간 뒤 위치를 계산하기 위해서는 Fredrick의 현재 위치 벡터 값과 Fredrick의 속력 벡터값을 더하면 된다. 

Vector2 position = new Vector2(5, 6);
Vector2 velocity = new Vector2(12, 5);
Debug.Log(position + velocity); // (17, 10)

계산을 하면 Fredrick은 1시간 뒤 (17, 10)에 도착하게 되므로, (17, 10)은 1시간뒤 Fredrick의 위치 벡터값이 된다.

 

2D 벡터와 3D 벡터의 다른점은 깊이를 나타내는 Z축의 값이 추가되는 것이다. 유니티는 왼손 좌표계를 사용한다. (검지가 Y, 엄지 = X, 중지 = Z)

 

Unity는 Vector3.magnitude를 통해 3D 공간에서도 벡터의 크기를 손쉽게 알 수 있다. 

Vector3 quentin = new Vector3(0, 0, 0);
Vector3 charles = new Vector3(12, 7, 5);
Debug.Log((charles - quentin).magnitude); // 14.76482

 

벡터의 내적 (Dot Product)

벡터의 내적이란 두 벡터사이의 스칼라 값이다. 두 벡터 A, B의 크기를 곱한다음 사이각도의 cosθ 값을 곱한 것이 내적이 되는데, 아래 사진에서 각도 뒤에 괄호 쳐져있는 부분이 내적값이다. 

 

 

직교하고 있는 두 벡터의 내적을 계산하면 0이, 각도를 계산하면 90이 나옴을 알 수 있다. 

Vector3 A = new Vector3(0, 7, 0);
Vector3 B = new Vector3(0, 0, 6);
Debug.Log(Vector3.Dot(A, B)); // 0
Debug.Log(Vector3.Angle(A, B)); // 90

 

 

내적은 게임에서 시야각 내에 물체가 위치하는지 판별할 때 사용할 수 있다. 플레이어의 시선벡터를 forward라고 하고, 시야각 135도라고하고 G와 O 그리고 추가적으로 너무 멀어서 보이지 않는 B(100, 1)가 있다고 가정할때 이들이 플레이어의 시야에 보이는지 판별하는 코드는 다음과 같다.

 

public class Vector : MonoBehaviour
{
    int sightAngle = 135;
    void Start()
    {
        Vector2 player = new Vector2(0, 0);
        Vector2 forward = new Vector2(0, 10);
        Vector2 G = new Vector2(1, 5);
        Vector2 B = new Vector2(100, 1);
        Vector2 O = new Vector2(-1, -1);


        Debug.Log("G is Visible: " + isTargetInSight(player, G, forward)); // True, theta = 11, dotProduct: 0.9805807
        Debug.Log("B is Visible: " + isTargetInSight(player, B, forward)); // False, theta = 89, dotProduct: 0.009999501
        Debug.Log("O is Visible: " + isTargetInSight(player, O, forward)); // False, theta = 135, dotProduct: -0.7071068
    }

    bool isTargetInSight(Vector2 player, Vector2 target, Vector2 forward)
    {
        Vector2 targetDirection = (target - player).normalized;
        float dotProduct = Vector2.Dot(forward.normalized, targetDirection);
        // 내적의 값이 > 0 이면 플레이어 앞에있고, < 0이면 뒤에있다.
        Debug.Log("dotProduct: " + dotProduct);
        // Target과 Player사이의 각도
        float theta = Mathf.Acos(dotProduct) * Mathf.Rad2Deg;
        Debug.Log("theta: " + theta);
        // 시야각 안에있는지 여부
        return theta <= sightAngle / 2;
    }
}

 

벡터의 외적 (Cross Prodcut)

벡터의 외적은 두 벡터에 대해 수직인 벡터를 만드는 연산이다. 유니티에서는 Vector3.Cross 함수를 제공하여 편리하게 벡터의 외적 계산을 할 수 있도록 도와주고 있다.

 


참고자료

https://bbungprogram.tistory.com/19

https://dallcom-forever2620.tistory.com/47

https://docs.unity3d.com/kr/530/Manual/UnderstandingVectorArithmetic.html

https://learn.unity.com/tutorial/vector-maths?uv=2019.3&projectId=5c8920b4edbc2a113b6bc26a#