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
|
|
|
|
}
|