2025-05-15 15:57:54 +09:00

124 lines
3.4 KiB
C#

using System;
using System.Collections;
using UnityEngine;
[Serializable]
public struct DamageEffectData
{
public int damage;
public float radius;
public float delay;
public LayerMask targetLayer;
public GameObject explosionEffectPrefab;
}
/// <summary>
/// AOE 범위 공격의 공통 로직을 처리하는 추상 베이스 클래스입니다.
/// </summary>
public abstract class AoeControllerBase : MonoBehaviour
{
[Header("경고 이펙트")]
[SerializeField] protected GameObject warningEffectInstance;
protected DamageEffectData _data;
private Action _slashAction;
private Action _destroyAction;
protected string EffectName;
/// <summary>
/// 범위 공격 이펙트를 설정하고, 딜레이 후 폭발을 실행합니다.
/// </summary>
public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction)
{
_data = data;
_slashAction = slashAction;
_destroyAction = destroyAction;
ShowWarningEffect();
StartCoroutine(ExplodeAfterDelay());
}
public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction, string effectName)
{
_data = data;
_slashAction = slashAction;
_destroyAction = destroyAction;
EffectName = effectName;
ShowWarningEffect();
StartCoroutine(ExplodeAfterDelay());
}
protected virtual void ShowWarningEffect()
{
if (warningEffectInstance != null)
warningEffectInstance.SetActive(true);
float diameter = _data.radius * 2f;
transform.localScale = new Vector3(diameter, 1f, diameter);
}
private IEnumerator ExplodeAfterDelay()
{
yield return new WaitForSeconds(_data.delay);
Explode();
}
/// <summary>
/// 폭발 이펙트 생성, 데미지 처리, 콜백 호출 순서로 실행합니다.
/// </summary>
protected virtual void Explode()
{
// 경고 이펙트 숨기기
if (warningEffectInstance != null)
warningEffectInstance.SetActive(false);
ShowDamageEffect();
// 슬래시 액션(애니메이션 트리거) 호출
_slashAction?.Invoke();
// 범위 내 데미지 처리
HitCheck();
// 패턴 클리어 콜백
_destroyAction?.Invoke();
// 자기 자신 제거
Destroy(gameObject, 2f);
}
protected virtual void HitCheck()
{
var hits = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer);
foreach (var hit in hits)
{
if (hit.CompareTag("Player"))
{
PlayerController playerController = hit.transform.GetComponent<PlayerController>();
if (playerController != null)
{
playerController.TakeDamage(_data.damage);
}
}
}
}
protected virtual void ShowDamageEffect()
{
// 폭발 이펙트 생성
if (_data.explosionEffectPrefab != null)
{
var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation);
effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius);
Destroy(effect, 2f);
}
}
protected virtual void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, _data.radius);
}
}