벡터의 내적
두 벡터의 방향이 얼마나 일치하는지 사용한다고 한다
로스트아크라는 게임에 백어택이라는 개념이 있다 몬스터의 엉덩이를 쳤을 때 백어택이 돼서 대미지가 더 들어가게 되는데 이걸 아마도 벡터의 내적을 이용해서 하지 않았을까 생각이 든다
이 글에서는 벡터의 내적에 대한 간단한 개념과 유니티에서 어떻게 사용되고 있는지 알아보고 간단한 예제를 만들어 보려고 한다~~~
내적
벡터에는 두가지 계산법이 있따
첫 번째
벡터 a b의 내적을 두 벡터의 크기와 두 벡터 사이의 각도를 이용하여 계산하는 방법이다
저 식의 원리는 코사인 제2법칙을 적용하면 간단하게 나온다
* 코사인 제2법칙 -> a^2 = b^2 + c^2 - a b Cosx
|a-b|^2를 분배 법칙과 코사인 제2법칙을 이용해서 풀이하고 양변에 같은 항을 소거하게 되면 저 식이 나오게 된다.
벡터 a b가 단위화된 벡터라면 벡터 a b의 내적은 코사인이 된다~~
벡터 a b의 성분을 이용해서 계산한 방법이다
저 식의 원리는 피타고라스 법칙을 적용하면 나온다
|a-b|^2를 분배 법칙과 피타고라스 법칙을 이용해 풀이하고 또 소거하게 되면 나온다
유니티에서는 내적을 어떻게 활용하고 있을까?
단위화한 두 벡터를 이용해서 코사인을 구하게 되고 나온 값을 이용해서
두 오브젝트가 서로 바라보고 있는지, 서로 직각인지, 반대 방향을 보고 있는지를 알 수 있다
유니티의 내장 함수인 Vector3.Dot이 있다.
또한 라이팅 쉐이더에도 사용되는데
빛이 들어오는 각도를 이용해 그림자를 구할 수 있게 된다
이번에는 내적을 이용해서 간단한 예제를 만들어보려고 한다.
게임에는 흔히 시야 시스템이 있다 이를 구현하기 위해서 FOV(Field of View)를 만들어야 한다
FOV(시야각)는 게임에서 캐릭터가 볼 수 있는 영역을 나타낸다 이를 내적을 활용하여 구현하면, 시야 내에 대상이 있는지 효율적으로 판단할 수 있다.
파란원 - 적 오브젝트가 자기 범위 안에 있는지 확인
초록부채꼴 - 플레이어 오브젝트의 시야 범위
빨간 선 - 적 감지
적 오브젝트가 초록 범위밖으로 가거나 장애물에 가려졌을 때 감지가 안 되는 것을 확인할 수 있다.
이런 기능은 적 오브젝트와 플레이어 오브젝트의 내적을 확인하고 내적값이 지정된 각도 범위 안에 있다면 탐지하도록 구현하였다
private void GetTargetInRange()
{
// 파란 원안에 들어온 오브젝트 감지
Collider[] detectedTargets = Physics.OverlapSphere(this.transform.position, viewDistance, targetLayer);
// 현재 리스트에 존재하는 타겟들 중 유효하지 않은 타겟 제거
List<Transform> targetsToRemove = new List<Transform>();
targets.RemoveAll(target =>
{
float distance = Vector3.Distance(transform.position, target.position);
return distance > viewDistance;
});
// 새롭게 탐지된 타겟을 추가
for (int i = 0; i < detectedTargets.Length; i++)
{
Transform target = detectedTargets[i].transform;
// 벡터 뺄셈으로 플레이어와 타겟의 오브젝트 방향 확인
Vector3 dir = (target.position - transform.position).normalized;
// 타겟과의 방향 벡터와 플레이어가 바라보는 방향 벡터간의 내적 확인
float dot = Vector3.Dot(transform.forward, dir);
// Dot함수는 코사인 값을 반환하므로 아크코사인으로 각도 확인
float angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
if (angle <= viewRange / 2)
{
// 피타고라스정리때 만들어놓은 함수 재활용ㅋㅋㅋ
float distance = PythagoreanTheorem.GetDistance(transform.position, target.position);
if (!Physics.Raycast(transform.position, dir, distance, obstacleLayer))
{
Debug.DrawLine(transform.position, target.position, Color.red);
if (!targets.Any(t => t == target)) // 중복 확인
targets.Add(target);
}
}
}
}
끝!!
'공부 > 게임 수학' 카테고리의 다른 글
삼각함수(tan) (1) | 2024.12.05 |
---|---|
삼각함수(Sin, Cos) (3) | 2024.12.04 |
벡터(Vector) (0) | 2024.12.01 |
피타고라스의 정리 (2) | 2024.12.01 |