내일배움캠프/TIL

내일배움캠프 28일차 TIL - 시야각 내의 오브젝트 판단하기

서보훈 2024. 10. 25. 21:10

스크립트의 필드에 오브젝트가 사용할 시야각(Field Of View) 를 float 형으로 선언하고, 이를통해 다른 오브젝트가 각도 이내에 들었는지 알아내는 방법입니다.

 

먼저 Mathf.Cos 를 사용하여, float 형인 FOV를 코사인값(각도값) 으로 변환합니다

private float fov = 45f;
private float threshold;

public Transform target;

public bool IsInFov()
{
    threshold = Mathf.Cos(fov * Mathf.Deg2Rad / 2);
}

 

여기서 fov 값에 Mathf.Deg2Rad를 곱하여 시야각인 45도를 라디안 값으로 변환해줍니다.

이 라디안 값을 Mathf.Cos() 를 사용하여 $Cos  \Theta $ 값을 구해줍니다.

 

여기서 각도값을 구할 때 좌, 우 무관하게 0 ~ 180 까지의 각도만 나오기 때문에 라디안을 반으로 나누어 절반의 각도인 22.5º 의 $Cos  \Theta $ 값을 구해줍니다.

이후 Vector2.Dot 를 사용하여 벡터간의 내적과 위에서 구한 Cos 값을 비교합니다.

private float fov = 45f;
private float threshold;

public Transform target;

public void IsInFov()
{
    threshold = Mathf.Cos(fov * Mathf.Deg2Rad / 2);
    Vector2 dir = target.position - transform.position;
    
    float cos = Vector2.Dot(dir.normalized, transform.up.normalized)
}

여기서 Vector2.Dot 에 사용하는 두 벡터는 다음과 같습니다.

  • 자신으로부터 대상이 이어지는 벡터의 정규값(길이가 1인 값)
  • 자신의 Y축으로으로 뻗어나가는 벡터의 정규값 (오른쪽 등으로 변경시, transform.right 등을 사용해 변경)

Vector2.Dot 연산은 벡터1의 길이 * 벡터2의 길이 * 두 벡터 사이의 $Cos  \Theta $ 의 값을 반환합니다.

두 벡터의 길이가 normalized, 길이가 1인 벡터이기 때문에 결과로 두 벡터 사이의 $Cos  \Theta $ 값을 구할 수 있습니다.

 

이제 fov와 두 벡터의 $Cos  \Theta $ 을 비교하여 대상이 fov 값 내에 들어왔는지 확인할 수 있습니다.

private float fov = 45f;
private float threshold;

public Transform target;

public void IsInFov()
{
    threshold = Mathf.Cos(fov * Mathf.Deg2Rad / 2);
    Vector2 dir = target.position - transform.position;
    
    float cos = Vector2.Dot(dir.normalized, transform.up.normalized)
    
    if(threshold <= cos)
    {
        return true;
    }
    
    return false;
}

이때, fov의 Cos 값보다 측정대상과의 Cos 값이 클 때 감지에 성공하도록 설정하여야 합니다.

Cos값은 0º 일때 1, 180º 일때 -1, 360º 일때 다시 1을 가지게되기 때문입니다.

 

또한, 180º 가 넘는값은 자연스럽게 반대의 값을 사용하여 내적을 구하기 때문에, 0 ~ 180 사이의 각도에 있는지 구하게 됩니다.

만약 좌, 우의 Fov 값을 다르게 설정하고 싶을경우, 두오브젝트의 transform.position 을 뺄 때 x값이 + 인 경우 우측, - 일경우 좌측 Fov를 사용해 계산해줄 수 있습니다.

 

또한 Dot 연산은 Vector3도 지원합니다.

단, Vector3 를 사용하는경우 3D 형태의 감지범위라는점을 인식해야 합니다.