Practice_Unity/Assets/Scripts/Equipment/Damage.cs
Seonkyu.kim e9ce829375 작업
1. 공격 스크립트를 만듬
  - 플레이어 -> 적 공격 테스트 (성공)
  - 적 -> 플레이어 공격 테스트 (성공)

Todo
1. 카메라 컨트롤러는 이거 방법 아예 따로 찾아야 할거 같음
2. 공격 스크립트 (시도)
  - 투사체 공격 (시작해야 함)
  - 공격 관련 무기 스테이터스 같은거 생각해야 함
  - 몬스터 AI라던가 설정 또는 이동과 관련된것도 생각해야 함
  - 공격 받았을 경우 처리는 어떻게 할건지 고민을 해야 함
2025-09-30 17:50:11 +09:00

98 lines
3.1 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 이 인터페이스를 구현한 오브젝트가 데미지를 받는것에 대해서 나타내기 위함
/// </summary>
public interface IDamageable
{
void TakeDamage(float damage);
}
/// <summary>
/// 무기나 투사체에 붙여 동작에 대한 트리거를 ON/OFF 하는 컴포넌트.
///
/// <!--Collider(Is Trigger(ON)) + Script 설정해둘것-->
/// <!-- 역할
/// 1. Collider를 공격 순간에만 ON/OFF 하는 판정 관리자 역할(인데 매니저라고 하기엔 그 역할이 약함)
/// 2. 충돌 처리하는 대상을 필터링 및 히트 쿨다운 정책 관리, 정보 전달
/// -->
/// <!-- 책임
/// 1. 데미지를 유발하는 것 (충돌 감지 및 데이터 전달)
/// -->
/// </summary>
public abstract class Damage : MonoBehaviour
{
[SerializeField] public LayerMask _targetlayer; // 공격 가능한 레이어 마스크
Collider _weaponCollider; // 공격 가능 시간만 활성화 되는 히트 센서로 활용하기 위해서 사용
protected readonly HashSet<GameObject> hitTargets = new HashSet<GameObject>();
// ToDo: 무기에 대한 여러 설정에 대한건 후에 Data_* 로 따로 관리
// 데미지, 다단히트, 히트 쿨타임, 넉백 등등
[SerializeField] private float _damage = 0f;
protected bool isActive = false; // 활성화 상태
public event Action<IDamageable, Collider> OnHit;
protected virtual void Awake()
{
if (_weaponCollider == null) _weaponCollider = GetComponent<Collider>();
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);
}