using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; public class SwingingArmMotionScript : MonoBehaviour { // Game Objects [SerializeField] private GameObject LeftHand; [SerializeField] private GameObject RightHand; [SerializeField] private GameObject MainCamera; [SerializeField] private ActionBasedContinuousMoveProvider _MoveProvider; // Vector3 Positions [SerializeField] private Vector3 PositionPreviousFrameLeftHand; [SerializeField] private Vector3 PositionPreviousFrameRightHand; [SerializeField] private Vector3 PlayerPositionPreviousFrame; [SerializeField] private Vector3 PlayerPositionCurrentFrame; [SerializeField] private Vector3 PositionCurrentFrameLeftHand; [SerializeField] private Vector3 PositionCurrentFrameRightHand; // Speed [SerializeField] private float BaseSpeed; // Базовая скорость [SerializeField] private float SprintSpeedMultiplier; // Множитель для бега [SerializeField] private float HandSpeedThreshold; // Порог скорости рук для бега private float CurrentSpeed; // Текущая скорость [SerializeField] private float HandSpeed; private float SmoothedSpeed; [SerializeField] private float SpeedSmoothingFactor; // Stamina (выносливость) [SerializeField] private float MaxStamina; // Максимальная выносливость [SerializeField] private float Stamina; // Текущая выносливость [SerializeField] private float StaminaDrainRate; // Скорость расхода выносливости (единиц/сек) [SerializeField] private float StaminaRecoveryRate; // Скорость восстановления (единиц/сек) [SerializeField] private float LowStaminaMultiplier; // Снижение скорости при низкой выносливости [SerializeField] private float StaminaRecoveryDelay; // Задержка перед восстановлением после израсходования [SerializeField] private bool IsRecovering = false; // Флаг для ожидания восстановления [SerializeField] private float RecoveryTimer; // Таймер восстановления [SerializeField] private bool IsPreRecovery = false; void Start() { BaseSpeed = _MoveProvider.moveSpeed; PlayerPositionPreviousFrame = transform.position; // Set current positions PositionPreviousFrameLeftHand = LeftHand.transform.position; // Set previous positions PositionPreviousFrameRightHand = RightHand.transform.position; CurrentSpeed = BaseSpeed; // Initialize to base speed SmoothedSpeed = BaseSpeed; Stamina = MaxStamina; // Инициализация выносливости } // Update is called once per frame void Update() { // Get positions of hands PositionCurrentFrameLeftHand = LeftHand.transform.position; PositionCurrentFrameRightHand = RightHand.transform.position; // Position of player PlayerPositionCurrentFrame = transform.position; // Get distance the hands and player has moved from last frame var playerDistanceMoved = Vector3.Distance(PlayerPositionCurrentFrame, PlayerPositionPreviousFrame); var leftHandDistanceMoved = Vector3.Distance(PositionPreviousFrameLeftHand, PositionCurrentFrameLeftHand); var rightHandDistanceMoved = Vector3.Distance(PositionPreviousFrameRightHand, PositionCurrentFrameRightHand); // Aggregate to get hand speed HandSpeed = ((leftHandDistanceMoved - playerDistanceMoved) + (rightHandDistanceMoved - playerDistanceMoved)); if (IsRecovering) { RecoveryTimer += Time.deltaTime; if (RecoveryTimer >= StaminaRecoveryDelay) { IsRecovering = false; RecoveryTimer = 0; } if (HandSpeed > HandSpeedThreshold) { CurrentSpeed = BaseSpeed; // Замедляем, если стамина истощена RecoveryTimer = 0; } } if (!IsRecovering) { Stamina += StaminaRecoveryRate * Time.deltaTime; // Восстанавливаем стамину Stamina = Mathf.Clamp(Stamina, 0, MaxStamina); if (IsPreRecovery) { if (Stamina >= 0.5*MaxStamina) { IsPreRecovery = false; } } if (HandSpeed > HandSpeedThreshold) { Stamina -= StaminaDrainRate * Time.deltaTime; // Уменьшаем стамину Stamina = Mathf.Clamp(Stamina, 0, MaxStamina); if (!IsPreRecovery) { CurrentSpeed = BaseSpeed * SprintSpeedMultiplier; // Замедляем, если стамина истощена } else if (IsPreRecovery) { CurrentSpeed = BaseSpeed; } } else { CurrentSpeed = BaseSpeed; } } if (Stamina <= 0) { IsRecovering = true; IsPreRecovery = true; } SmoothedSpeed = Mathf.Lerp(SmoothedSpeed, CurrentSpeed, SpeedSmoothingFactor); _MoveProvider.moveSpeed = SmoothedSpeed; // Set previous position of hands for next frame PositionPreviousFrameLeftHand = PositionCurrentFrameLeftHand; PositionPreviousFrameRightHand = PositionCurrentFrameRightHand; // Set player position previous frame PlayerPositionPreviousFrame = PlayerPositionCurrentFrame; } }