2026-01-29 06:58:38 +00:00
|
|
|
|
using UnityEngine;
|
2026-02-01 15:49:12 +00:00
|
|
|
|
using System.Collections;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
|
|
|
|
|
|
public class PlayerMovement : MonoBehaviour
|
|
|
|
|
|
{
|
2026-01-29 16:11:10 +00:00
|
|
|
|
[Header("--- 참조 ---")]
|
2026-01-29 06:58:38 +00:00
|
|
|
|
[SerializeField] private Stats stats;
|
|
|
|
|
|
[SerializeField] private PlayerHealth health;
|
|
|
|
|
|
[SerializeField] private PlayerAnimator pAnim;
|
2026-01-30 07:45:11 +00:00
|
|
|
|
[SerializeField] private PlayerAttack attackScript;
|
2026-01-29 16:11:10 +00:00
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
[Header("--- 대시 설정 ---")]
|
|
|
|
|
|
// ⭐ 유저님 이미지(image_42ccbd.png) 수치를 기본값으로 적용했습니다.
|
|
|
|
|
|
[SerializeField] private float dashDistance = 3f;
|
|
|
|
|
|
[SerializeField] private float dashDuration = 0.08f;
|
|
|
|
|
|
[SerializeField] private float dashCooldown = 1.5f;
|
|
|
|
|
|
|
2026-01-29 16:11:10 +00:00
|
|
|
|
[Header("--- 차징 감속 설정 ---")]
|
|
|
|
|
|
[Range(0.1f, 1f)]
|
2026-01-30 07:45:11 +00:00
|
|
|
|
[SerializeField] private float minSpeedMultiplier = 0.3f;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
|
|
|
|
|
|
private Vector3 _moveDir;
|
|
|
|
|
|
private bool _isSprinting;
|
2026-02-01 15:49:12 +00:00
|
|
|
|
private bool _isDashing;
|
|
|
|
|
|
private float _lastDashTime;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// ⭐ PlayerInput에서 호출하는 입력 세팅
|
2026-01-29 06:58:38 +00:00
|
|
|
|
public void SetMoveInput(Vector3 dir, bool sprint) { _moveDir = dir; _isSprinting = sprint; }
|
|
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// ⭐ PlayerInput에서 Space를 누를 때 호출하는 대시 시도 함수
|
|
|
|
|
|
public void AttemptDash()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (CanDash()) StartCoroutine(DashRoutine());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool CanDash()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 쿨타임 체크 + 대시 중 아님 + 사망 아님
|
|
|
|
|
|
bool isCooldownOver = Time.time >= _lastDashTime + dashCooldown;
|
|
|
|
|
|
bool isAlive = health != null && !health.IsDead;
|
|
|
|
|
|
return isCooldownOver && !_isDashing && isAlive;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-29 06:58:38 +00:00
|
|
|
|
private void Update()
|
|
|
|
|
|
{
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// 1. 💀 사망, ⚡ 대시 중, 🤕 혹은 피격(isHit) 중일 때 이동 차단
|
|
|
|
|
|
if (health != null && (health.IsDead || health.isHit || _isDashing))
|
2026-01-29 06:58:38 +00:00
|
|
|
|
{
|
2026-02-01 15:49:12 +00:00
|
|
|
|
if (pAnim != null && !health.IsDead) pAnim.UpdateMove(0f);
|
2026-01-29 06:58:38 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// 2. ⚔️ 공격 중(콤보 및 후딜레이)일 때 이동 차단
|
2026-01-30 07:45:11 +00:00
|
|
|
|
if (attackScript != null && attackScript.IsAttacking)
|
|
|
|
|
|
{
|
2026-02-01 15:49:12 +00:00
|
|
|
|
if (pAnim != null) pAnim.UpdateMove(0f);
|
2026-01-30 07:45:11 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// 3. 이동 속도 계산 및 차징 감속 적용
|
2026-01-29 06:58:38 +00:00
|
|
|
|
float speed = _isSprinting ? stats.CurrentRunSpeed : stats.CurrentMoveSpeed;
|
2026-01-29 16:11:10 +00:00
|
|
|
|
|
|
|
|
|
|
if (attackScript != null && attackScript.IsCharging)
|
|
|
|
|
|
{
|
|
|
|
|
|
float speedReduction = Mathf.Lerp(1.0f, minSpeedMultiplier, attackScript.ChargeProgress);
|
|
|
|
|
|
speed *= speedReduction;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// 4. 실제 이동 처리
|
2026-01-29 06:58:38 +00:00
|
|
|
|
transform.Translate(_moveDir * speed * Time.deltaTime, Space.World);
|
|
|
|
|
|
|
2026-02-01 15:49:12 +00:00
|
|
|
|
// 5. 애니메이션 연동
|
2026-01-29 06:58:38 +00:00
|
|
|
|
if (pAnim != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
float animVal = _moveDir.magnitude > 0.1f ? (_isSprinting ? 1.0f : 0.5f) : 0f;
|
2026-01-30 07:45:11 +00:00
|
|
|
|
if (attackScript != null && attackScript.IsCharging) animVal *= 0.5f;
|
2026-01-29 06:58:38 +00:00
|
|
|
|
pAnim.UpdateMove(animVal);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-01 15:49:12 +00:00
|
|
|
|
|
|
|
|
|
|
// ⭐ [핵심] 방향성 대시 및 무적 처리 로직
|
|
|
|
|
|
private IEnumerator DashRoutine()
|
|
|
|
|
|
{
|
|
|
|
|
|
_isDashing = true;
|
|
|
|
|
|
_lastDashTime = Time.time;
|
|
|
|
|
|
|
|
|
|
|
|
// 입력 방향이 있으면 그쪽으로, 없으면 캐릭터의 정면이 아닌 후방(회피)으로 대시
|
|
|
|
|
|
Vector3 dashDir = _moveDir.sqrMagnitude > 0.001f ? _moveDir : -transform.forward;
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ [무적] 대시 시작 시 무적 상태 활성화
|
|
|
|
|
|
if (health != null) health.isInvincible = true;
|
|
|
|
|
|
|
|
|
|
|
|
float startTime = Time.time;
|
|
|
|
|
|
while (Time.time < startTime + dashDuration)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 속도 = 거리 / 시간
|
|
|
|
|
|
float speed = dashDistance / dashDuration;
|
|
|
|
|
|
transform.Translate(dashDir * speed * Time.deltaTime, Space.World);
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ [무적] 대시 종료 시 무적 상태 해제
|
|
|
|
|
|
if (health != null) health.isInvincible = false;
|
|
|
|
|
|
_isDashing = false;
|
|
|
|
|
|
}
|
2026-01-29 06:58:38 +00:00
|
|
|
|
}
|