Deff_Dev
[Unity/C#] 2D 부채꼴 범위 탐색 본문
이 글에서는 게임 수학에 관한 자세한 내용은 다루지 않고 사용법과 왜 쓰는지에 대해 설명하겠다.
게임 수학에 관한 자세한 설명은 다른 블로그를 찾아보면 자세하게 설명되어있으니 다른 블로그 참고하면 된다.
만들어 볼 기능
위처럼 로켓(삼각형)이 바라보고 있는 방향의 부채꼴 범위 안에 들어온 오브젝트를 탐지하는 기능을 만들어보겠다.
이 글에서 설명하는 프로젝트는 2D이기 때문에 Vector2를 기준으로 설명하겠다.
내적
내적은 Vector2.Dot(vector , vector)로 사용 가능하다.
그럼 내적을 왜 쓸까 ?
내적은 플레이어가 바라보는 방향과 물체의 사이 각도의 코사인 값를 구하기 위해 사용한다.
Vector2.dot(오브젝트가 바라보는 방향, 타겟의 방향);
이런 식으로 내적을 사용할 수 있고 내적에 들어가는 매개변수는 정규화된 벡터를 사용한다.
정규화된 벡터를 사용하는 이유는 정규화된 벡터의 내적을 구한다면 각도의 코사인 값이 나오기 때문이다.
Cos 값은 -1부터 1까지 나오고 플레이어가 위를 바라보고 있다면 1에 가까워진다.
그렇다면 내적한 값이 1하고 가까워진다면 플레이어가 바라보는 방향과 가까워진다는 것을 알 수 있다.
내적 값을 어떻게 이용할까 ?
내적으로 구한 값을 로켓의 시야각 / 2 코사인 값과 비교한다면 부채꼴 안에 들어왔는지를 확인할 수 있다.
시야각 / 2를 하는 이유는 코사인은 Y축 대칭이기 때문에 시야가 90도라고 한다면 반 절인 45도의 코사인 값을 구해서 내적 값과 비교하는 것이다.
그럼 코드로 어떻게 적용할까 ?
using System;
using UnityEditor;
using UnityEngine;
public class AlertSystem : MonoBehaviour
{
// fov가 45라면 45도 각도안에 있는 aesteriod를 인식할 수 있음.
[SerializeField] private float fov = 45f;
// radius가 10이라면 반지름 10 범위에서 aesteriod들을 인식할 수 있음.
[SerializeField] private float radius = 10f;
private float alertThreshold;
private Animator animator;
private static readonly int blinking = Animator.StringToHash("isBlinking");
public Transform aestreiod;
private Color color = new Color(0, 1, 0, 0.3f);
private void Start()
{
animator = GetComponent<Animator>();
// FOV를 라디안으로 변환하고 코사인 값을 계산
alertThreshold = Mathf.Cos(fov / 2 * Mathf.Deg2Rad);
}
private void Update()
{
CheckAlert();
}
private void CheckAlert()
{
// 물체의 방향을 구한다.
Vector2 targetDir = aestreiod.position - transform.position;
if (targetDir.magnitude <= radius) // 오브젝트가 플레이어의 탐지 범위에 들어올 때
{
// 내적
float dot = Vector2.Dot(transform.up, targetDir.normalized);
// 내적한 값이 각도 / 2 코사인 값보다 크다면 => 플레이어가 바라보는 방향에 더 가깝다면
if (dot >= alertThreshold)
{
animator.SetBool(blinking, true); // 탐지
}
else
{
animator.SetBool(blinking, false);
}
}
else
{
animator.SetBool(blinking, false);
}
}
private void OnDrawGizmos() // 씬 창에서 부채꼴 범위 그리기
{
Handles.color = color;
// 시야의 시작 방향 벡터 계산
Vector2 startDirection = Quaternion.Euler(0, 0, fov / 2) * transform.up;
// DrawSolidArc 함수를 이용하여 시야 범위를 나타내는 부채꼴 그리기
Handles.DrawSolidArc(transform.position, Vector3.back, startDirection, fov, radius);
}
}
'Unity(유니티) > 유니티 공부' 카테고리의 다른 글
[Unity/C#] 오브젝트 풀 구현 (0) | 2024.05.19 |
---|---|
[Unity/C#] 배경 이미지 무한 스크롤 (0) | 2024.05.18 |
[Unity C#] Trigger와 Action을 이용한 NPC 대화 구현 (0) | 2024.05.12 |
[Unity/C#] 프로퍼티를 왜 쓰는가 ? (0) | 2024.04.23 |
[Unity/C#] 패턴 매칭 (0) | 2024.04.13 |