moonee-e3 님의 블로그
2024-05-28 시야각에 들어오면 죽이는 적 구현 본문
최종 코드 (BlueEnemy)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlueEnemy : MonoBehaviour
{
// 참고 링크 https://nicotina04.tistory.com/197
// 시야 영역의 반지름과 시야 각도 조절하는 코드
public float viewRadius; // 시야 범위
[Range(0, 360)]
public float viewAngle; // 시야 각도
public GameObject HitCircle; // 범위 나타내는 오브젝트
// 마스크 2종 //타켓과 오브젝트
public LayerMask targetMask, obstacleMask; // 타켓과 장애물을 나눔
// Target mask에 ray hit된 transform을 보관하는 리스트
public List<Transform> visibleTargets = new List<Transform>();
void Start()
{
StartCoroutine(HitPoint());
StartCoroutine(HitTimeCheck());
}
bool IsHit = true;
IEnumerator HitPoint()
{
while (true)
{
while (IsHit)
{
FindVisibleTargets();
yield return null;
}
// 비활성화
HitCircle.gameObject.SetActive(false);
// 3초 동안 대기
yield return new WaitForSeconds(3f);
IsHit = true;
}
}
IEnumerator HitTimeCheck()
{
while (true)
{
if (IsHit)
{
yield return new WaitForSeconds(3f);
IsHit = false;
}
yield return null;
}
}
void FindVisibleTargets()
{
HitCircle.gameObject.SetActive(true); // 공격 범위 나타냄
visibleTargets.Clear(); // 타겟값 초기화
// viewRadius를 반지름으로 한 원 영역 내 targetMask 레이어인 콜라이더를 모두 가져옴
Collider[] targetsInViewRadius = Physics.OverlapSphere(transform.position, viewRadius, targetMask);
for (int i = 0; i < targetsInViewRadius.Length; i++)
{
Transform target = targetsInViewRadius[i].transform;
Vector3 dirToTarget = (target.position - transform.position).normalized;
// 플레이어와 forward와 target이 이루는 각이 설정한 각도 내라면
if (Vector3.Angle(transform.forward, dirToTarget) < viewAngle / 2)
{
float dstToTarget = Vector3.Distance(transform.position, target.transform.position);
// 타겟으로 가는 레이캐스트에 obstacleMask가 걸리지 않으면 visibleTargets에 Add
if (!Physics.Raycast(transform.position, dirToTarget, dstToTarget, obstacleMask))
{
visibleTargets.Add(target); // 타켓에 추가
Player.Die(); // 타켓이 플레이어 밖에 없어서 Player.die() 실행 Player말고 다른 오브제가 있다면 if문 걸어주기
StopCoroutine("HitPoint");
StopCoroutine("HitTimeCheck");
}
}
}
}
// y축 오일러 각을 3차원 방향 벡터로 변환한다.
// 원본과 구현이 살짝 다름에 주의. 결과는 같다.
public Vector3 DirFromAngle(float angleDegrees, bool angleIsGlobal)
{
if (!angleIsGlobal)
{
angleDegrees += transform.eulerAngles.y;
}
return new Vector3(Mathf.Cos((-angleDegrees + 90) * Mathf.Deg2Rad), 0, Mathf.Sin((-angleDegrees + 90) * Mathf.Deg2Rad));
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
{
Player.Die();
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Enemy2))]
public class EnemyView : Editor
{
void OnSceneGUI()
{
Enemy2 fow = (Enemy2)target;
Handles.color = Color.white;
Handles.DrawWireArc(fow.transform.position, Vector3.up, Vector3.forward, 360, fow.viewRadius);
Vector3 viewAngleA = fow.DirFromAngle(-fow.viewAngle / 2, false);
Vector3 viewAngleB = fow.DirFromAngle(fow.viewAngle / 2, false);
Handles.DrawLine(fow.transform.position, fow.transform.position + viewAngleA * fow.viewRadius);
Handles.DrawLine(fow.transform.position, fow.transform.position + viewAngleB * fow.viewRadius);
Handles.color = Color.red;
foreach (Transform visible in fow.visibleTargets)
{
Handles.DrawLine(fow.transform.position, visible.transform.position);
}
}
}
Editor를 활용해 유니티에서 범위가 보이게 함
Editor 파일에 넣어야 빌드할 때 오류 안남!
2024-05-28 시야 각에 들어오면 죽이는 적 구현
2024-05-29 코루틴을 추가해서 3초마다 감지하게 했지만 켜진 직후에만 감지하고 감지를 못함
2024-05-30 IsHit과 IsHitTime 코루틴을 추가해서 오류 수정
'개발 일지 [3D | Dream Forest]' 카테고리의 다른 글
2024-06-14 | 포탈_닿으면 플레이어 위치 이동 (0) | 2024.06.22 |
---|---|
2024-05-31 | 3D에서 2D 스프라이트 화면에 맞게 나타내기 (0) | 2024.06.22 |
2024-05-25 같은 위치 반복해서 움직이는 적 (0) | 2024.06.22 |
2024-05-20 플레이어의 카메라 시점 변경 (0) | 2024.06.21 |
Dream Forest 개발 일지 날짜별 정리 (0) | 2024.06.20 |