Projext/Assets/Scripts/Enemy/AI/ExplodeMonster.cs

95 lines
5.4 KiB
C#
Raw Normal View History

2026-02-13 09:11:54 +00:00
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 -> 자폭 몬스터를
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
[Header("=== 자폭 설정 ===")] // 인스펙터 제목을 달거에요 -> 자폭 설정을
[SerializeField] private float explodeRange = 4f; // 변수를 선언할거에요 -> 폭발 범위를
[SerializeField] private float triggerRange = 2.5f; // 변수를 선언할거에요 -> 감지 범위를
[SerializeField] private float fuseTime = 1.5f; // 변수를 선언할거에요 -> 지연 시간을
[SerializeField] private float explosionDamage = 50f; // 변수를 선언할거에요 -> 폭발 데미지를
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
[Header("이펙트")] // 인스펙터 제목을 달거에요 -> 이펙트를
[SerializeField] private GameObject explosionEffectPrefab; // 변수를 선언할거에요 -> 폭발 이펙트를
[SerializeField] private ParticleSystem fuseEffect; // 변수를 선언할거에요 -> 도화선 이펙트를
[SerializeField] private AudioClip fuseSound; // 변수를 선언할거에요 -> 도화선 소리를
[SerializeField] private AudioClip explosionSound; // 변수를 선언할거에요 -> 폭발 소리를
[Header("애니메이션")] // 인스펙터 제목을 달거에요 -> 애니메이션을
[SerializeField] private string runAnim = "Monster_Run"; // 변수를 선언할거에요 -> 달리기 애니 이름을
[SerializeField] private string fuseAnim = "Monster_Fuse"; // 변수를 선언할거에요 -> 점화 애니 이름을
private bool hasExploded = false; // 변수를 선언할거에요 -> 폭발 여부를
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
protected override void Init() // 함수를 실행할거에요 -> 초기화 Init을
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
if (agent != null) agent.stoppingDistance = 0.5f; // 설정을 바꿀거에요 -> 정지 거리를 짧게
2026-02-04 14:06:25 +00:00
}
2026-02-13 09:11:54 +00:00
protected override void ExecuteAILogic() // 함수를 실행할거에요 -> AI 로직을
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
if (isHit || isAttacking || hasExploded) return; // 조건이 맞으면 중단할거에요 -> 행동 불가면
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
float dist = Vector3.Distance(transform.position, playerTransform.position); // 거리를 계산할거에요 -> 플레이어와의
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
if (dist <= triggerRange) // 조건이 맞으면 실행할거에요 -> 감지 거리 안이면
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
StartCoroutine(ExplodeRoutine()); // 코루틴을 실행할거에요 -> 자폭 시퀀스를
2026-02-04 14:06:25 +00:00
}
2026-02-13 09:11:54 +00:00
else // 조건이 틀리면 실행할거에요 -> 멀면
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
ChasePlayer(); // 함수를 실행할거에요 -> 추격을
2026-02-04 14:06:25 +00:00
}
}
2026-02-13 09:11:54 +00:00
private void ChasePlayer() // 함수를 선언할거에요 -> 추격 로직을
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
if (agent.isOnNavMesh) // 조건이 맞으면 실행할거에요 -> 내비게이션 위라면
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
agent.isStopped = false; // 명령을 내릴거에요 -> 이동 재개
agent.SetDestination(playerTransform.position); // 명령을 내릴거에요 -> 플레이어 위치로
2026-02-04 14:06:25 +00:00
}
2026-02-13 09:11:54 +00:00
animator.Play(runAnim); // 재생할거에요 -> 달리기 애니를
2026-02-04 14:06:25 +00:00
}
2026-02-13 09:11:54 +00:00
private IEnumerator ExplodeRoutine() // 코루틴 함수를 정의할거에요 -> 자폭 과정을
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
isAttacking = true; // 상태를 바꿀거에요 -> 공격 중으로 (이동 불가)
hasExploded = true; // 상태를 바꿀거에요 -> 폭발 됨으로 (중복 방지)
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
if (agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; } // 명령을 내릴거에요 -> 정지
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
// 1. 점화
animator.Play(fuseAnim); // 재생할거에요 -> 점화 애니를
if (fuseEffect != null) fuseEffect.Play(); // 실행할거에요 -> 도화선 효과를
if (fuseSound != null) audioSource.PlayOneShot(fuseSound); // 재생할거에요 -> 도화선 소리를
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
yield return new WaitForSeconds(fuseTime); // 기다릴거에요 -> 지연 시간만큼
2026-02-04 14:06:25 +00:00
2026-02-13 09:11:54 +00:00
// 2. 폭발
Explode(); // 함수를 실행할거에요 -> 폭발 처리를
2026-02-04 14:06:25 +00:00
}
2026-02-13 09:11:54 +00:00
private void Explode() // 함수를 선언할거에요 -> 실제 폭발 로직을
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
if (explosionEffectPrefab != null) Instantiate(explosionEffectPrefab, transform.position, Quaternion.identity); // 생성할거에요 -> 폭발 이펙트를
if (explosionSound != null) AudioSource.PlayClipAtPoint(explosionSound, transform.position); // 재생할거에요 -> 폭발 소리를
2026-02-05 15:42:48 +00:00
2026-02-13 09:11:54 +00:00
// 범위 데미지 처리
Collider[] hits = Physics.OverlapSphere(transform.position, explodeRange); // 배열에 담을거에요 -> 범위 내 충돌체들을
foreach (var hit in hits) // 반복할거에요 -> 충돌체마다
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
if (hit.CompareTag("Player")) // 조건이 맞으면 실행할거에요 -> 플레이어라면
2026-02-04 14:06:25 +00:00
{
2026-02-13 09:11:54 +00:00
var hp = hit.GetComponent<IDamageable>(); // 가져올거에요 -> 체력 인터페이스를
if (hp != null) hp.TakeDamage(explosionDamage); // 실행할거에요 -> 폭발 데미지 입히기를
2026-02-04 14:06:25 +00:00
}
}
2026-02-13 09:11:54 +00:00
// 자폭이므로 몬스터 사망
currentHP = 0; // 값을 설정할거에요 -> 체력을 0으로
Die(); // 실행할거에요 -> 사망 함수를
2026-02-04 14:06:25 +00:00
}
2026-02-13 09:11:54 +00:00
protected override void OnStartHit() { } // 가상 함수를 비울거에요 -> 피격 되어도 멈추지 않게 (슈퍼아머)
2026-02-05 15:42:48 +00:00
}