| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |
- 연습
- LookAt
- 프로그래밍
- spritelibrary
- 스파르타내일배움캠프TIL
- 게임분석
- 취업
- 컴포넌트
- 유니티
- 게임 회사
- 취미
- 까먹기전에메모
- 후기
- 블렌더
- materialpropertyblock
- 뭐드라
- spritemask2d
- 점프
- til
- ag 내일배움캠프
- 공부
- 붕괴스타레일
- 내일배움캠프
- 코딩
- 스파르타내일배움캠프
- 붕괴 스타레일
- 게임용어
- 원신
- 나만의 견해
- c#
- Today
- Total
덴바의 노트
내일배움캠프 21일차 TIL : 기존 시야각 구하기 문제점 해결 본문

오늘의 키워드
- 기존 시야각 구현 코드의 문제점
문제 파악
<< 변경 전 >>
private void CheckAlert()
{
colliders = Physics2D.OverlapCircleAll(transform.position, radius, targetMask);
if (colliders.Length > 0)
{
foreach (var enemy in colliders)
{
Vector3 enemyDir = (enemy.transform.position - transform.position).normalized;
float dot = Vector2.Dot(transform.up, enemyDir);
float theta = Mathf.Acos(dot) * Mathf.Rad2Deg;
if (theta <= fov * 0.5f)
{
animator.SetBool(blinking, true);
}
else
{
animator.SetBool(blinking, false);
}
}
}
else
{
animator.SetBool(blinking, false);
}
}
(문제되는 코드)
float theta = Mathf.Acos(dot) * Mathf.Rad2Deg;
기존 방식은 두 벡터의 내적을 구한 후
내적을 구한 부분에서 Degree를 추출하는 방식으로 코드가 이어졌습니다.
코드 작동 상 문제는 없습니다!
하지만 약간의 비효율적인 부분이 생기게 됩니다.
그 이유는 Acos에 있습니다.
Sin, Cos, Tan, Asin, Acos, Atan 등의 연산은 생각 외로 무겁다는 것 입니다.
왜 비효율적이었는지에 대해서 오늘 강의에 들은 내용을 토대로 설명하고자 합니다.
<< 변경 후 코드>>
private void Start()
{
animator = GetComponent<Animator>();
// FOV를 라디안으로 변환하고 코사인 값을 계산
alertThreshold = Mathf.Cos((fov * 0.5f) * Mathf.Deg2Rad);
}
private void CheckAlert()
{
colliders = Physics2D.OverlapCircleAll(transform.position, radius, targetMask);
if (colliders.Length > 0)
{
foreach (var enemy in colliders)
{
bool needAlert = false;
Vector3 enemyDir = (enemy.transform.position - transform.position).normalized;
float dot = Vector3.Dot(transform.up, enemyDir);
if (alertThreshold <= dot)
{
needAlert = true;
break;
}
animator.SetBool(blinking, needAlert);
}
}
else
{
animator.SetBool(blinking, false);
}
}
Vector3 enemyDir = (enemy.transform.position - transform.position).normalized;
float dot = Vector3.Dot(transform.up, enemyDir);
이 부분은 본인 위치에서 적의 방향을 구해내는 코드입니다.
그리고 본인을 중점으로 위로의 방향과 적 방향을 내적으로 구합니다.
이를 그림으로 표현하면 아래와 같습니다.

Transform.UP은 Vector3(0, 1, 0)을 뜻하고
enemyDir 또한 normalized를 했기 때문에 그 값은 1이 될 것입니다.
여기서 핵심은
Vector2.Dot()
즉, 내적을 구하는 공식은
A * B * Cos θ라는 것 입니다.
그리고 우리는 A와 B값이 각자 1인 것을 알고 있습니다.
이 뜻은 Vector2.Dot() => Cos θ 라는 것입니다.
그렇기 때문에 굳이 Acos을 이용하여 각을 구할 필요가 없던 것입니다.
또한 위 Start문에서
alertThreshold = Mathf.Cos((fov * 0.5f) * Mathf.Deg2Rad)
이를 한 번 계산하여 제한되는 임계점 radian 값이 몇인지를 알 수 있으며,
if (alertThreshold <= dot)
내적의 결과 값이 alertThreshold. 즉 임계점 보다 클 경우
대상은 시야각에 들어온 것으로 처리할 수 있습니다.
오늘의 회고
이렇게 해서 최종적으로 시야각에 관한 포스팅을 마무리했습니다.
처음에는 매우 복잡하고 어려워서 구현하지 못했지만
이번 강의로 사이다 마냥 완벽하게 이해됐습니다.
내적의 결과가 세타각의 radian 값을 출력할 줄은 꿈에도 몰랐네요...
'프로그래밍 노트 > TIL' 카테고리의 다른 글
| 내일배움캠프 24일차 TIL : SpriteLibrary #2 (0) | 2024.05.22 |
|---|---|
| 내일배움캠프 23일차 TIL : SpriteLibrary (0) | 2024.05.21 |
| 내일배움캠프 20일차 TIL : 수학을 이용한 시야각 구하기 (0) | 2024.05.16 |
| 내일배움캠프 19일차 TIL (0) | 2024.05.14 |
| 내일배움캠프 18일차 TIL (0) | 2024.05.13 |