1. 공격 스크립트를 만듬 - 플레이어 -> 적 공격 테스트 (성공) - 적 -> 플레이어 공격 테스트 (성공) Todo 1. 카메라 컨트롤러는 이거 방법 아예 따로 찾아야 할거 같음 2. 공격 스크립트 (시도) - 투사체 공격 (시작해야 함) - 공격 관련 무기 스테이터스 같은거 생각해야 함 - 몬스터 AI라던가 설정 또는 이동과 관련된것도 생각해야 함 - 공격 받았을 경우 처리는 어떻게 할건지 고민을 해야 함
98 lines
3.1 KiB
C#
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);
|
|
|
|
|
|
|
|
}
|