using System.Collections; using UnityEngine; // ReSharper disable once CheckNamespace namespace BlueWaterProject { public class CombatMovement : MonoBehaviour, IRigidMovable, IDashable { // Components public Rigidbody Rb { get; set; } private Transform visualLook; private CombatStatus combatStatus; // Move [Range(1f, 10f), Tooltip("이동 속도")] [SerializeField] private float moveSpeed = 7f; // Dash [field: Range(1f, 50f), Tooltip("대쉬 속도")] [field: SerializeField] public float DashSpeed { get; set; } = 20f; [field: Range(0.1f, 1f), Tooltip("대쉬 시간")] [field: SerializeField] public float DashTime { get; set; } = 0.2f; [field: Range(0f, 5f), Tooltip("대쉬 쿨타임")] [field: SerializeField] public float DashCooldown { get; set; } = 0.5f; public bool EnableDash { get; set; } = true; private bool isDashing; public bool IsDashing { get => isDashing; set { isDashing = value; iAnimationStateController.SetAnimationParameter(CombatPlayerAnimationParameter.IS_DASHING, IsDashing); } } // Interfaces private IAnimationStateController iAnimationStateController; private IMeleeComboAttackable iMeleeComboAttackable; // Variables private Vector3 currentMoveDirection; private Vector3 previousMoveDirection = Vector3.back; public Vector3 PreviousMoveDirection { get => previousMoveDirection; set { previousMoveDirection = value; iAnimationStateController.SetAnimationParameter(CombatPlayerAnimationParameter.X_DIRECTION, PreviousMoveDirection.x); iAnimationStateController.SetAnimationParameter(CombatPlayerAnimationParameter.Z_DIRECTION, PreviousMoveDirection.z); } } private Coroutine dashCoroutine; private float finalSpeed; private bool isMoving; public bool IsMoving { get => isMoving; set { isMoving = value; iAnimationStateController.SetAnimationParameter(CombatPlayerAnimationParameter.IS_MOVING, isMoving); } } public bool EnableMove { get; set; } = true; // Events public delegate void StartDashEvent(); public event StartDashEvent OnStartDash; public delegate void EndDashEvent(); public event EndDashEvent OnEndDash; // Unity events private void Start() { combatStatus = GetComponent(); iAnimationStateController = GetComponent(); iMeleeComboAttackable = GetComponent(); } private void Update() { FlipVisualLook(); } private void FixedUpdate() { if (!EnableMove || IsDashing) return; if (combatStatus.IsStunned) { IsMoving = false; return; } ApplyMovement(); } // Init public void InitComponent(Rigidbody rb, Transform visualLook) { Rb = rb; this.visualLook = visualLook; } // Event methods public void HandleInputMovement(Vector2 movementInput) { currentMoveDirection = new Vector3(movementInput.x, 0, movementInput.y).normalized; } public void HandleDash() { if (!CanMove()) return; if (iMeleeComboAttackable.CurrentComboAttackCount > 0) { iMeleeComboAttackable.EndComboAttack(); } dashCoroutine = StartCoroutine(nameof(DashCoroutine)); } public void HandleAttackInDash() { if (IsDashing) { EndDash(DashCooldown); } } public void HandleEnableMove() => EnableMove = true; public void HandleDisableMove() => EnableMove = false; public void HandleEnableMoveAndDash() { EnableMove = true; EnableDash = true; } public void HandleDisableMoveAndDash() { EnableMove = false; EnableDash = false; } // Methods private void FlipVisualLook() { var localScale = visualLook.localScale; localScale.x = PreviousMoveDirection.x switch { > 0.01f => Mathf.Abs(localScale.x), < -0.01f => -Mathf.Abs(localScale.x), _ => localScale.x }; visualLook.localScale = localScale; } private void ApplyMovement() { if (currentMoveDirection != Vector3.zero) { PreviousMoveDirection = currentMoveDirection; } IsMoving = currentMoveDirection != Vector3.zero; var slowCoefficient = combatStatus.IsSlowedMoveSpeed ? combatStatus.MoveSpeedCoefficient : 1f; var finalVelocity = currentMoveDirection * (moveSpeed * slowCoefficient); Rb.velocity = finalVelocity; } private bool CanMove() { return EnableDash && !IsDashing; } private IEnumerator DashCoroutine() { StartDash(); var dashDirection = PreviousMoveDirection; var animationStarted = false; yield return StartCoroutine(iAnimationStateController.WaitForAnimationToRun(CombatPlayerAnimationName.DASH_STATE, success => animationStarted = success)); if (!animationStarted) { EndDash(0); yield break; } iAnimationStateController.SetCurrentAnimationSpeed(DashTime); while (iAnimationStateController.IsComparingCurrentAnimation(CombatPlayerAnimationName.DASH_STATE) && iAnimationStateController.GetCurrentAnimationNormalizedTime() < 1f) { //var finalVelocity = rb.position + dashDirection * (dashSpeed * Time.fixedDeltaTime); //rb.MovePosition(finalVelocity); var finalVelocity = dashDirection * DashSpeed; Rb.velocity = finalVelocity; yield return new WaitForFixedUpdate(); } EndDash(DashCooldown); } private void StartDash() { OnStartDash?.Invoke(); EnableDash = false; IsDashing = true; } public void EndDash(float dashCooldown) { if (dashCoroutine != null) { StopCoroutine(dashCoroutine); dashCoroutine = null; } Rb.velocity = Vector3.zero; iAnimationStateController.ResetAnimationSpeed(); OnEndDash?.Invoke(); IsDashing = false; StartCoroutine(Utils.CoolDown(dashCooldown, () => EnableDash = true)); } } }