2026-05-18 기획 수정 : 플레이어와 에너미의 body간 충돌은 없다
This commit is contained in:
66
Assets/02_Scripts/Combat/AttackHitbox.cs
Normal file
66
Assets/02_Scripts/Combat/AttackHitbox.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(CircleCollider2D))]
|
||||
public class AttackHitbox : MonoBehaviour
|
||||
{
|
||||
private CircleCollider2D _collider;
|
||||
private int _damage;
|
||||
private Vector2 _hitVelocity;
|
||||
private string _hitReactionState;
|
||||
private LayerMask _targetLayer;
|
||||
private readonly HashSet<IDamageable> _alreadyHit = new();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_collider = GetComponent<CircleCollider2D>();
|
||||
// The player body does not collide with enemies; this trigger is the only attack contact.
|
||||
_collider.isTrigger = true;
|
||||
_collider.enabled = false;
|
||||
}
|
||||
|
||||
public void Activate(ActionData data, Vector2 localPosition, Vector2 hitVelocity, LayerMask targetLayer)
|
||||
{
|
||||
transform.localPosition = localPosition;
|
||||
_collider.radius = data.Radius;
|
||||
_damage = data.Damage;
|
||||
_hitVelocity = hitVelocity;
|
||||
_hitReactionState = data.HitReactionAnimationState;
|
||||
_targetLayer = targetLayer;
|
||||
_alreadyHit.Clear();
|
||||
_collider.enabled = true;
|
||||
|
||||
// Catch enemies already inside the hitbox on the same frame it opens.
|
||||
ScanImmediateOverlap();
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
_collider.enabled = false;
|
||||
_alreadyHit.Clear();
|
||||
}
|
||||
|
||||
private void ScanImmediateOverlap()
|
||||
{
|
||||
Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, _collider.radius, _targetLayer);
|
||||
foreach (var hit in hits)
|
||||
TryDamage(hit);
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other) => TryDamage(other);
|
||||
private void OnTriggerStay2D(Collider2D other) => TryDamage(other);
|
||||
|
||||
private void TryDamage(Collider2D other)
|
||||
{
|
||||
if ((_targetLayer.value & (1 << other.gameObject.layer)) == 0) return;
|
||||
|
||||
// Hurtboxes may live on child objects, while damage handling usually lives on the root.
|
||||
if (!other.TryGetComponent<IDamageable>(out var target))
|
||||
target = other.GetComponentInParent<IDamageable>();
|
||||
if (target == null) return;
|
||||
if (_alreadyHit.Contains(target)) return;
|
||||
|
||||
_alreadyHit.Add(target);
|
||||
target.TakeDamage(_damage, _hitVelocity, _hitReactionState);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user