using System; using System.Collections.Generic; using UnityEngine; /// /// 이 인터페이스를 구현한 오브젝트가 데미지를 받는것에 대해서 나타내기 위함 /// public interface IDamageable { void TakeDamage(float damage); } /// /// 무기나 투사체에 붙여 동작에 대한 트리거를 ON/OFF 하는 컴포넌트. /// /// /// /// /// public abstract class Damage : MonoBehaviour { [SerializeField] public LayerMask _targetlayer; // 공격 가능한 레이어 마스크 Collider _weaponCollider; // 공격 가능 시간만 활성화 되는 히트 센서로 활용하기 위해서 사용 protected readonly HashSet hitTargets = new HashSet(); // ToDo: 무기에 대한 여러 설정에 대한건 후에 Data_* 로 따로 관리 // 데미지, 다단히트, 히트 쿨타임, 넉백 등등 [SerializeField] private float _damage = 0f; protected bool isActive = false; // 활성화 상태 public event Action OnHit; protected virtual void Awake() { if (_weaponCollider == null) _weaponCollider = GetComponent(); if (_weaponCollider != null) { _weaponCollider.isTrigger = true; _weaponCollider.enabled = false; } } protected virtual bool LayerPassed(Collider target) { int layer = target.gameObject.layer; return (_targetlayer.value & (1 << layer)) != 0; } protected void ApplyDamage(Collider target) { if(!isActive) return; if(!LayerPassed(target)) return; GameObject go = target.gameObject; if(hitTargets.Contains(go)) return; if (target.TryGetComponent(out IDamageable damagebable)) { hitTargets.Add(go); damagebable.TakeDamage(_damage); OnHit?.Invoke(damagebable, target); OnDamageApplied(target); } } public void SetTriggerActive(bool active) { isActive = active; if (_weaponCollider != null) _weaponCollider.enabled = active; if (active) ResetHitCache(); } protected void ResetHitCache() => hitTargets.Clear(); private void OnTriggerEnter(Collider other) { HandleCollision(other); } // 데미지 적용 후의 특화 동작 오버라이드 하기 protected virtual void OnDamageApplied(Collider target) { // 예: 피격 효과, 사운드 재생 등 // 투사체면 충돌시 파괴, 근접 무기면 히트 이펙트 재생이나 연속 공격 위해 아무것도 안하기 } protected abstract void HandleCollision(Collider other); }