본문 바로가기

C#

[C#] 벡터의 내적

1. 서론

이번 글은 벡터의 내적과 삼각함수를 이용하여, 오브젝트의 시야각 범위를 구현해 보는 시간을 가질 것이다.

코드는 단순하지만 벡터의 성질과 내적과 삼각함수를 모른다면, 복잡한 코드만 난무해질 것이다.

오히려 더 단순해질 수 도있나? 유니티에서 리네임 된 코드 내부는 아마 비슷하겠지...

2. 본론

그림1. 벡터의 내적 공식

벡터 A, B 내적은 A벡터와 B벡터의 크기를 곱하고 사이 각에 코사인 세타 값을 곱한 스칼라 값이 된다.

스칼라 값은 벡터가 아닌 물리량인 것이다.

 

그림2. 시야각 구현 샘플 이미지

우리는 우선 시야각을 활용해서 적이 앞에 있는지 없는지만 판별해 볼 것이다. 

 

플레이어의 방향벡터와 시아 각의 범위를 정해줄 필요가 있다.

그림3. 이런식이다~ 이말이야

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public float m_fRadi;//시야 각
    public Transform m_TransObj; //범위밖에 있는지 없는지 체크할 오브젝트(이하 적 이라고 표현함)
    
    private void Update()
    {
    	//적 위치와 플레이어 위치간의 단위벡터를 구함
        Vector3 dirToTarget = (m_TransObj.transform.position - transform.position).normalized;
        
        //dot(내적)함수를 이용해 플레이어 forward방향과 적과의 단위벡터를 내적함.
        float Theta = Vector3.Dot(this.transform.forward, dirToTarget);
        
        //내적한 결과값인 스칼라값이 시야각을 코사인 계산 한 값 범위안에 있는지 검출.
        if (Theta > Mathf.Cos((m_fRadi / 2) * Mathf.Deg2Rad))
        {
            Debug.Log("시야각 범위에있다");
        }

        ColBoundary();
        Drawline();
    }
    
    //바운더리 계산
    //그려줄 때와 계속 변화한 값을 계산해주기 위한 함수.
    private Vector3 m_VecLeft;
    private Vector3 m_VecRight;
    private void ColBoundary()
    {
        m_VecLeft = ColAngle(-m_fRadi / 2);
        m_VecRight = ColAngle(m_fRadi / 2);
    }

	//플레이어가 로테이션 값이 변화함에 따라 플레이어의 각도 값도 같이 움직여야 하기때문에,
    //앵글에 플레이어의 앵글 y축을 더해줌.
    private Vector3 ColAngle(float _fAngle)
    {
        _fAngle += transform.eulerAngles.y;
        return new Vector3(Mathf.Sin(_fAngle * Mathf.Deg2Rad), 0, Mathf.Cos(_fAngle * Mathf.Deg2Rad));
    }
    
    //단순히 그리기 위한 함수
    private void Drawline()
    {
        Debug.DrawLine(transform.position, transform.position + m_VecLeft * 10, Color.blue);
        Debug.DrawLine(transform.position, transform.position + m_VecRight * 10, Color.blue);
    }
}

 

3. 결론

추가적으로, " ( A*B / |A|*|B| ) arcos = 사이각"  이 나오게 된다.

 

사이각을 모르지만 벡터를 알고 있다면, 각 까지도 구할 수 있게 된다.

 

 

그냥 개발하느냐와 못하느냐 구현한 것들이 효율적이냐 효율적이지 않냐는 2차적인 문제인 것이라고 생각이 든다.

 

시간은 일정 부분 정해져 있고, 일단은 구현해 내는 게 더 중요하다고 보는 것이다.

이건 비효율적이어서 안될 것 같고, 이건 구현하기 힘들고, 어렵고.

 

그렇게 시간 허비하지 말고, 구현하다 보면 새로운 아이디어와 새로운 방법이 보인다는 것이다.

일단 구현해보자. 구현해놔야 컴파일러로 효율성을 따질 것 아닌가?