2026-05-15 충돌오류 진행중
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
public class Enemy : MonoBehaviour, IDamageable
|
||||
{
|
||||
[Header("Stats")]
|
||||
@@ -10,14 +11,28 @@ public class Enemy : MonoBehaviour, IDamageable
|
||||
[SerializeField] private float _hitFlashDuration = 0.1f;
|
||||
[SerializeField] private Color _hitFlashColor = Color.red;
|
||||
|
||||
[Header("Hit Bounce")]
|
||||
[SerializeField] private float _hitReactionDuration = 0.5f;
|
||||
[SerializeField] private float _airborneHitYVelocity = 3f;
|
||||
[SerializeField] private float _wallBounceVelocityMultiplier = 0.8f;
|
||||
[SerializeField] private float _wallBounceMinXVelocity = 1f;
|
||||
[SerializeField] private float _wallBounceUpwardVelocity = 1.5f;
|
||||
|
||||
private int _currentHealth;
|
||||
private Rigidbody2D _rb;
|
||||
private Animator _anim;
|
||||
private SpriteRenderer _spriteRenderer;
|
||||
private Color _originalColor;
|
||||
private float _flashTimer;
|
||||
private float _hitReactionTimer;
|
||||
private bool _isGrounded;
|
||||
private Vector2 _lastVelocity;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_currentHealth = _maxHealth;
|
||||
_rb = GetComponent<Rigidbody2D>();
|
||||
_anim = GetComponentInChildren<Animator>();
|
||||
_spriteRenderer = GetComponentInChildren<SpriteRenderer>();
|
||||
if (_spriteRenderer != null)
|
||||
_originalColor = _spriteRenderer.color;
|
||||
@@ -31,9 +46,18 @@ private void Update()
|
||||
if (_flashTimer <= 0f && _spriteRenderer != null)
|
||||
_spriteRenderer.color = _originalColor;
|
||||
}
|
||||
|
||||
if (_hitReactionTimer > 0f)
|
||||
_hitReactionTimer -= Time.deltaTime;
|
||||
}
|
||||
|
||||
public void TakeDamage(int amount)
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (_rb != null)
|
||||
_lastVelocity = _rb.linearVelocity;
|
||||
}
|
||||
|
||||
public void TakeDamage(int amount, Vector2 hitVelocity = default, string hitReactionAnimationState = null)
|
||||
{
|
||||
if (_currentHealth <= 0) return;
|
||||
|
||||
@@ -46,10 +70,89 @@ public void TakeDamage(int amount)
|
||||
_flashTimer = _hitFlashDuration;
|
||||
}
|
||||
|
||||
if (_anim != null && !string.IsNullOrEmpty(hitReactionAnimationState))
|
||||
_anim.Play(hitReactionAnimationState);
|
||||
|
||||
if (_rb != null)
|
||||
{
|
||||
Vector2 nextVelocity = GetHitReactionVelocity(hitVelocity);
|
||||
if (nextVelocity != Vector2.zero)
|
||||
{
|
||||
_rb.linearVelocity = nextVelocity;
|
||||
_hitReactionTimer = _hitReactionDuration;
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentHealth <= 0)
|
||||
Die();
|
||||
}
|
||||
|
||||
private void OnCollisionEnter2D(Collision2D collision)
|
||||
{
|
||||
UpdateGroundedState(collision);
|
||||
|
||||
if (_hitReactionTimer <= 0f || _rb == null) return;
|
||||
if (collision.collider.GetComponentInParent<PlayerController>() != null) return;
|
||||
|
||||
for (int i = 0; i < collision.contactCount; i++)
|
||||
{
|
||||
Vector2 normal = collision.GetContact(i).normal;
|
||||
if (Mathf.Abs(normal.x) < 0.5f) continue;
|
||||
|
||||
BounceOffWall(normal);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollisionStay2D(Collision2D collision)
|
||||
{
|
||||
UpdateGroundedState(collision);
|
||||
}
|
||||
|
||||
private void OnCollisionExit2D(Collision2D collision)
|
||||
{
|
||||
_isGrounded = false;
|
||||
}
|
||||
|
||||
private Vector2 GetHitReactionVelocity(Vector2 hitVelocity)
|
||||
{
|
||||
if (_hitReactionTimer <= 0f || _isGrounded)
|
||||
return hitVelocity;
|
||||
|
||||
Vector2 currentVelocity = _rb.linearVelocity;
|
||||
Vector2 nextVelocity = hitVelocity == Vector2.zero ? currentVelocity : hitVelocity;
|
||||
nextVelocity.y = _airborneHitYVelocity;
|
||||
return nextVelocity;
|
||||
}
|
||||
|
||||
private void UpdateGroundedState(Collision2D collision)
|
||||
{
|
||||
for (int i = 0; i < collision.contactCount; i++)
|
||||
{
|
||||
if (collision.GetContact(i).normal.y > 0.5f)
|
||||
{
|
||||
_isGrounded = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BounceOffWall(Vector2 wallNormal)
|
||||
{
|
||||
Vector2 incomingVelocity = _lastVelocity.sqrMagnitude > _rb.linearVelocity.sqrMagnitude
|
||||
? _lastVelocity
|
||||
: _rb.linearVelocity;
|
||||
|
||||
if (Mathf.Abs(incomingVelocity.x) < _wallBounceMinXVelocity) return;
|
||||
|
||||
Vector2 bouncedVelocity = Vector2.Reflect(incomingVelocity, wallNormal) * _wallBounceVelocityMultiplier;
|
||||
if (bouncedVelocity.y < _wallBounceUpwardVelocity)
|
||||
bouncedVelocity.y = _wallBounceUpwardVelocity;
|
||||
|
||||
_rb.linearVelocity = bouncedVelocity;
|
||||
_hitReactionTimer = _hitReactionDuration;
|
||||
}
|
||||
|
||||
private void Die()
|
||||
{
|
||||
Debug.Log($"{name} 사망");
|
||||
|
||||
Reference in New Issue
Block a user