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; // Максимальная выносливость public float MaxStamina { get { return _MaxStamina; } } [SerializeField] private float _Stamina; // Текущая выносливость public float Stamina { get { return _Stamina; } set { _Stamina = value; } } [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; public bool IsPreRecovery { get { return _IsPreRecovery; } } 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; } }