공격 및 추적 로직 버그 수정 및 개선

DefenceScene 내 메쉬 변경
카메라 각도 수정
This commit is contained in:
2026-01-13 19:35:30 +09:00
parent 3b22d26865
commit 01106fe34c
9 changed files with 1218 additions and 1116 deletions

View File

@@ -5,31 +5,49 @@ public class EnemyAttack : MonoBehaviour
{
[Header("Attack Settings")]
public float damage = 10f;
public float attackRange = 2.0f;
public float attackRange = 0.5f; // 표면 기준이므로 0.5~1.0 정도면 충분합니다.
public float attackCooldown = 1.0f;
[Header("Visual Feedback")]
public Renderer enemyRenderer;
[ColorUsage(true, true)] public Color flashEmissionColor = Color.white * 3f;
public float flashDuration = 0.1f;
private Material _enemyMaterial;
private Color _originalEmissionColor;
private float _nextAttackTime;
private Transform _target;
private IDamageable _targetDamageable;
private EnemyMoveDefault _moveScript;
private Collider _targetCollider; // 타겟의 콜라이더 캐싱
// 쉐이더 프로퍼티 ID (문자열보다 성능이 좋음)
private static readonly int EmissionColorProp = Shader.PropertyToID("_EmissionColor");
void Awake()
{
_moveScript = GetComponent<EnemyMoveDefault>();
if (enemyRenderer == null) enemyRenderer = GetComponentInChildren<Renderer>();
if (enemyRenderer != null)
{
_enemyMaterial = enemyRenderer.material;
_enemyMaterial.EnableKeyword("_EMISSION");
_originalEmissionColor = _enemyMaterial.GetColor(EmissionColorProp);
}
}
void Update()
{
// 이동 스크립트로부터 현재 목표를 실시간으로 가져옵니다.
if (_target == null)
if (_moveScript != null && _moveScript.Target != _target)
{
// EnemyMoveDefault에서 _target을 public이나 프로퍼티로 만들어 가져오세요
_target = GetComponent<EnemyMoveDefault>().Target;
if (_target != null) _targetDamageable = _target.GetComponent<IDamageable>();
return;
SetAttackTarget(_moveScript.Target);
}
float distance = Vector3.Distance(transform.position, _target.position);
if (_target == null) return;
// --- 거리 계산 방식 수정 (핵심) ---
float distance = GetDistanceToTarget();
// 사거리 안에 있고 타겟이 살아있을 때만 공격
if (distance <= attackRange)
{
if (Time.time >= _nextAttackTime)
@@ -39,24 +57,28 @@ public class EnemyAttack : MonoBehaviour
}
}
private float GetDistanceToTarget()
{
if (_targetCollider == null) return Vector3.Distance(transform.position, _target.position);
// 타겟의 표면상에서 내 위치와 가장 가까운 점을 찾습니다.
Vector3 closestPoint = _targetCollider.ClosestPoint(transform.position);
// 내 발밑(transform.position)과 그 표면 사이의 실제 거리를 계산합니다.
return Vector3.Distance(transform.position, closestPoint);
}
private void Attack()
{
if (_target == null) return;
if (_targetDamageable == null)
{
_targetDamageable = _target.GetComponentInParent<IDamageable>();
}
if (_targetDamageable == null) _targetDamageable = _target.GetComponentInParent<IDamageable>();
if (_targetDamageable != null)
{
_targetDamageable.TakeDamage(damage);
_nextAttackTime = Time.time + attackCooldown;
}
else
{
// 대상이 IDamageable이 아니거나 이미 파괴됨
_target = null;
StartCoroutine(FlashEmissionRoutine());
Debug.Log($"[공격!] 대상: {_target.name}");
}
}
@@ -64,6 +86,24 @@ public class EnemyAttack : MonoBehaviour
{
_target = newTarget;
if (_target != null)
_targetDamageable = _target.GetComponent<IDamageable>();
{
_targetCollider = _target.GetComponentInChildren<Collider>();
_targetDamageable = _target.GetComponentInParent<IDamageable>();
}
else
{
_targetCollider = null;
_targetDamageable = null;
}
}
private IEnumerator FlashEmissionRoutine()
{
if (_enemyMaterial != null)
{
_enemyMaterial.SetColor(EmissionColorProp, flashEmissionColor);
yield return new WaitForSeconds(flashDuration);
_enemyMaterial.SetColor(EmissionColorProp, _originalEmissionColor);
}
}
}