diff --git a/Game/CourierOld/Assets/Code/Gameplay/Player/CharacterController.cs b/Game/CourierOld/Assets/Code/Gameplay/Player/CharacterController.cs index 5c1b3ca..d4ae4f5 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Player/CharacterController.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Player/CharacterController.cs @@ -14,6 +14,7 @@ namespace Code.Gameplay.Player public Quaternion CameraRotation; // Текущее вращение камеры для определения направления движения public CameraMode CameraMode; // Текущий режим камеры для адаптации поведения public Vector3 CameraPlanarDirection; // Направление камеры в горизонтальной плоскости + public bool JumpPressed; // Флаг указывающий, нажата ли кнопка прыжка } /* @@ -32,8 +33,12 @@ namespace Code.Gameplay.Player private float maxStableMoveSpeed = 10f, // Максимальная скорость движения по устойчивой поверхности stableMovementSharpness = 15f, // Резкость изменения скорости движения (чем выше - тем резче) - orientationSharpness = 10f; // Резкость изменения вращения персонажа (чем выше - тем резче) + orientationSharpness = 10f, // Резкость изменения вращения персонажа (чем выше - тем резче) + jumpSpeed = 10f; // Скорость прыжка + [SerializeField] + private Vector3 gravity = new(0, -30f, 0); // Вектор, отвечающий за применение гравитации + // Векторы движения и направления взгляда private Vector3 _moveInputVector, _lookInputVector; @@ -43,8 +48,10 @@ namespace Code.Gameplay.Player // Вращение камеры в FirstPerson режиме для синхронизации (только горизонтальная компонента) private Quaternion _firstPersonCameraRotation; - // Флаг указывающий, что нужно применить вращение камеры к персонажу - private bool _shouldApplyCameraRotation; + + private bool + _shouldApplyCameraRotation, // Флаг указывающий, что нужно применить вращение камеры к персонажу + _jumpRequested; // Флаг указывающий, что был запрошен прыжок // Инициализация контроллера private void Start() @@ -72,6 +79,10 @@ namespace Code.Gameplay.Player { HandleThirdPersonInputs(ref inputs, moveInputVector); } + + // При запрашивании прыжка + if (inputs.JumpPressed) + _jumpRequested = true; } // Обработка ввода для FirstPerson режима @@ -180,28 +191,51 @@ namespace Code.Gameplay.Player // Обновление скорости движения персонажа public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime) { - // Сохранение текущей величины скорости - var currentVelocityMagnitude = currentVelocity.magnitude; - - // Получение нормали поверхности для корректного движения по наклонным плоскостям - var effectiveGroundNormal = motor.GroundingStatus.GroundNormal; - - // Переориентация текущей скорости вдоль поверхности - currentVelocity = motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) * currentVelocityMagnitude; + // Если персонаж находится на земле + if (motor.GroundingStatus.IsStableOnGround) + { + // Сохранение текущей величины скорости + var currentVelocityMagnitude = currentVelocity.magnitude; - // Переориентация входного вектора движения вдоль поверхности - var inputRight = Vector3.Cross(_moveInputVector, motor.CharacterUp); - var reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized * _moveInputVector.magnitude; - - // Расчет целевой скорости движения с учетом ограничения максимальной скорости - var targetMovementVelocity = reorientedInput * maxStableMoveSpeed; - - // Плавная интерполяция текущей скорости к целевой с экспоненциальным сглаживанием - currentVelocity = Vector3.Lerp( - currentVelocity, - targetMovementVelocity, - 1f - Mathf.Exp(-stableMovementSharpness * deltaTime) - ); + // Получение нормали поверхности для корректного движения по наклонным плоскостям + var effectiveGroundNormal = motor.GroundingStatus.GroundNormal; + + // Переориентация текущей скорости вдоль поверхности + currentVelocity = motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) * + currentVelocityMagnitude; + + // Переориентация входного вектора движения вдоль поверхности + var inputRight = Vector3.Cross(_moveInputVector, motor.CharacterUp); + var reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized * + _moveInputVector.magnitude; + + // Расчет целевой скорости движения с учетом ограничения максимальной скорости + var targetMovementVelocity = reorientedInput * maxStableMoveSpeed; + + // Плавная интерполяция текущей скорости к целевой с экспоненциальным сглаживанием + currentVelocity = Vector3.Lerp( + currentVelocity, + targetMovementVelocity, + 1f - Mathf.Exp(-stableMovementSharpness * deltaTime) + ); + + // Если запрошен прыжок + if (_jumpRequested) + { + currentVelocity += motor.CharacterUp * jumpSpeed - Vector3.Project(currentVelocity, motor.CharacterUp); + _jumpRequested = false; + motor.ForceUnground(); + } + } + + // Если персонаж не находится на земле + else + { + // Применяем гравитацию + currentVelocity += gravity * deltaTime; + // Отменяем прыжок (фикс проблемы с двойным прыжком после приземления) + _jumpRequested = false; + } } // Метод вызывается перед обновлением персонажа (можно использовать для подготовки) diff --git a/Game/CourierOld/Assets/Code/Gameplay/Player/Player.cs b/Game/CourierOld/Assets/Code/Gameplay/Player/Player.cs index c135e8b..350ddbe 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Player/Player.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Player/Player.cs @@ -57,6 +57,7 @@ public class Player : MonoBehaviour var moveInput = _inputService.MoveInput; inputs.MoveAxisForward = moveInput.y; // Vertical ось (W/S или Up/Down) inputs.MoveAxisRight = moveInput.x; // Horizontal ось (A/D или Left/Right) + inputs.JumpPressed = _inputService.JumpPressed; // Прыжки (Space) // Передаем информацию о камере для адаптивного поведения inputs.CameraRotation = playerCamera.transform.rotation; diff --git a/Game/CourierOld/Assets/Code/Gameplay/Player/PlayerCamera.cs b/Game/CourierOld/Assets/Code/Gameplay/Player/PlayerCamera.cs index bbee991..392ed4a 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Player/PlayerCamera.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Player/PlayerCamera.cs @@ -37,9 +37,6 @@ namespace Code.Gameplay.Player // Скорость зума камеры distanceMovementSpeed = 5f, // Множитель скорости изменения дистанции при зуме - // Скорость интерполяции текущая -> целевая позиция зума - distanceMovementSharpness = 100f, // Коэффициент плавности изменения дистанции (чем выше - тем резче) - // Скорость поворота камеры rotationSpeed = 0.3f, // Множитель скорости вращения камеры diff --git a/Game/CourierOld/Assets/Code/Input/IInputService.cs b/Game/CourierOld/Assets/Code/Input/IInputService.cs index 9a27af8..4dd0357 100644 --- a/Game/CourierOld/Assets/Code/Input/IInputService.cs +++ b/Game/CourierOld/Assets/Code/Input/IInputService.cs @@ -13,6 +13,7 @@ namespace Code.Input // Для управления движением персонажа Vector2 MoveInput { get; } + bool JumpPressed { get; } // Для переключения режима камеры bool ToggleCameraModePressed { get; } diff --git a/Game/CourierOld/Assets/Code/Input/InputService.cs b/Game/CourierOld/Assets/Code/Input/InputService.cs index 9c5509f..38e77f8 100644 --- a/Game/CourierOld/Assets/Code/Input/InputService.cs +++ b/Game/CourierOld/Assets/Code/Input/InputService.cs @@ -12,6 +12,7 @@ namespace Code.Input public Vector2 LookInput { get; private set; } public float ZoomInput { get; private set; } public Vector2 MoveInput { get; private set; } + public bool JumpPressed { get; private set; } public bool ToggleCameraModePressed { get; private set; } public InputService(InputActionAsset inputActionAsset) @@ -56,6 +57,14 @@ namespace Code.Input moveAction.canceled += OnMoveCanceled; } + // Обработка прыжков (персонаж) + var jumpAction = gameplayMap.FindAction("Jump"); + if (jumpAction != null) + { + jumpAction.performed += OnJumpPerformed; + jumpAction.canceled += OnJumpCanceled; + } + // Обработка переключения режима камеры var toggleCameraModeAction = gameplayMap.FindAction("ToggleCameraMode"); if (toggleCameraModeAction != null) @@ -95,6 +104,16 @@ namespace Code.Input MoveInput = Vector2.zero; } + private void OnJumpPerformed(InputAction.CallbackContext context) + { + JumpPressed = true; + } + + private void OnJumpCanceled(InputAction.CallbackContext context) + { + JumpPressed = false; + } + private void OnToggleCameraModePerformed(InputAction.CallbackContext context) { ToggleCameraModePressed = true; @@ -127,6 +146,9 @@ namespace Code.Input gameplayMap.FindAction("Move").performed -= OnMovePerformed; gameplayMap.FindAction("Move").canceled -= OnMoveCanceled; + gameplayMap.FindAction("Jump").performed -= OnJumpPerformed; + gameplayMap.FindAction("Jump").canceled -= OnJumpCanceled; + gameplayMap.FindAction("ToggleCameraMode").performed -= OnToggleCameraModePerformed; gameplayMap.FindAction("ToggleCameraMode").canceled -= OnToggleCameraModeCanceled; } diff --git a/Game/CourierOld/Assets/Resources/Scenes/MovementDev.unity b/Game/CourierOld/Assets/Resources/Scenes/MovementDev.unity index 6c42b91..1197926 100644 --- a/Game/CourierOld/Assets/Resources/Scenes/MovementDev.unity +++ b/Game/CourierOld/Assets/Resources/Scenes/MovementDev.unity @@ -989,6 +989,8 @@ MonoBehaviour: maxStableMoveSpeed: 10 stableMovementSharpness: 15 orientationSharpness: 10 + jumpSpeed: 10 + gravity: {x: 0, y: -30, z: 0} --- !u!1 &1959874989 GameObject: m_ObjectHideFlags: 0 diff --git a/Game/CourierOld/Assets/Settings/Input/InputSystem_Actions.inputactions b/Game/CourierOld/Assets/Settings/Input/InputSystem_Actions.inputactions index bf96e82..d6c191b 100644 --- a/Game/CourierOld/Assets/Settings/Input/InputSystem_Actions.inputactions +++ b/Game/CourierOld/Assets/Settings/Input/InputSystem_Actions.inputactions @@ -565,9 +565,9 @@ "initialStateCheck": false }, { - "name": "Attack", + "name": "Jump", "type": "Button", - "id": "6c2ab1b8-8984-453a-af3d-a3c78ae1679a", + "id": "f1ba0d36-48eb-4cd5-b651-1c94a6531f70", "expectedControlType": "", "processors": "", "interactions": "", @@ -582,42 +582,6 @@ "interactions": "Hold", "initialStateCheck": false }, - { - "name": "Crouch", - "type": "Button", - "id": "27c5f898-bc57-4ee1-8800-db469aca5fe3", - "expectedControlType": "Button", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, - { - "name": "Jump", - "type": "Button", - "id": "f1ba0d36-48eb-4cd5-b651-1c94a6531f70", - "expectedControlType": "Button", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, - { - "name": "Previous", - "type": "Button", - "id": "2776c80d-3c14-4091-8c56-d04ced07a2b0", - "expectedControlType": "Button", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, - { - "name": "Next", - "type": "Button", - "id": "b7230bb6-fc9b-4f52-8b25-f5e19cb2c2ba", - "expectedControlType": "", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, { "name": "Sprint", "type": "Button", @@ -626,20 +590,18 @@ "processors": "", "interactions": "", "initialStateCheck": false + }, + { + "name": "Slide", + "type": "Button", + "id": "27c5f898-bc57-4ee1-8800-db469aca5fe3", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false } ], "bindings": [ - { - "name": "", - "id": "978bfe49-cc26-4a3d-ab7b-7d7a29327403", - "path": "/leftStick", - "interactions": "", - "processors": "", - "groups": ";Gamepad", - "action": "Move", - "isComposite": false, - "isPartOfComposite": false - }, { "name": "WASD", "id": "00ca640b-d935-4593-8157-c05846ea39b3", @@ -739,61 +701,6 @@ "isComposite": false, "isPartOfComposite": true }, - { - "name": "", - "id": "1635d3fe-58b6-4ba9-a4e2-f4b964f6b5c8", - "path": "/{Primary2DAxis}", - "interactions": "", - "processors": "", - "groups": "XR", - "action": "Move", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "3ea4d645-4504-4529-b061-ab81934c3752", - "path": "/stick", - "interactions": "", - "processors": "", - "groups": "Joystick", - "action": "Move", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "c1f7a91b-d0fd-4a62-997e-7fb9b69bf235", - "path": "/rightStick", - "interactions": "", - "processors": "", - "groups": ";Gamepad", - "action": "Look", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "8c8e490b-c610-4785-884f-f04217b23ca4", - "path": "/delta", - "interactions": "", - "processors": "", - "groups": ";Touch", - "action": "Look", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "3e5f5442-8668-4b27-a940-df99bad7e831", - "path": "/{Hatswitch}", - "interactions": "", - "processors": "", - "groups": "Joystick", - "action": "Look", - "isComposite": false, - "isPartOfComposite": false - }, { "name": "", "id": "f8ca1921-4be2-4067-8199-ffea9bcefeee", @@ -805,94 +712,6 @@ "isComposite": false, "isPartOfComposite": false }, - { - "name": "", - "id": "143bb1cd-cc10-4eca-a2f0-a3664166fe91", - "path": "/buttonWest", - "interactions": "", - "processors": "", - "groups": ";Gamepad", - "action": "Attack", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "05f6913d-c316-48b2-a6bb-e225f14c7960", - "path": "/leftButton", - "interactions": "", - "processors": "", - "groups": ";Keyboard&Mouse", - "action": "Attack", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "886e731e-7071-4ae4-95c0-e61739dad6fd", - "path": "/primaryTouch/tap", - "interactions": "", - "processors": "", - "groups": ";Touch", - "action": "Attack", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "ee3d0cd2-254e-47a7-a8cb-bc94d9658c54", - "path": "/trigger", - "interactions": "", - "processors": "", - "groups": "Joystick", - "action": "Attack", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "8255d333-5683-4943-a58a-ccb207ff1dce", - "path": "/{PrimaryAction}", - "interactions": "", - "processors": "", - "groups": "XR", - "action": "Attack", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "b3c1c7f0-bd20-4ee7-a0f1-899b24bca6d7", - "path": "/enter", - "interactions": "", - "processors": "", - "groups": "Keyboard&Mouse", - "action": "Attack", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "cbac6039-9c09-46a1-b5f2-4e5124ccb5ed", - "path": "/2", - "interactions": "", - "processors": "", - "groups": "Keyboard&Mouse", - "action": "Next", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "e15ca19d-e649-4852-97d5-7fe8ccc44e94", - "path": "/dpad/right", - "interactions": "", - "processors": "", - "groups": "Gamepad", - "action": "Next", - "isComposite": false, - "isPartOfComposite": false - }, { "name": "", "id": "f2e9ba44-c423-42a7-ad56-f20975884794", @@ -904,28 +723,6 @@ "isComposite": false, "isPartOfComposite": false }, - { - "name": "", - "id": "8cbb2f4b-a784-49cc-8d5e-c010b8c7f4e6", - "path": "/leftStickPress", - "interactions": "", - "processors": "", - "groups": "Gamepad", - "action": "Sprint", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "d8bf24bf-3f2f-4160-a97c-38ec1eb520ba", - "path": "/trigger", - "interactions": "", - "processors": "", - "groups": "XR", - "action": "Sprint", - "isComposite": false, - "isPartOfComposite": false - }, { "name": "", "id": "eb40bb66-4559-4dfa-9a2f-820438abb426", @@ -937,50 +734,6 @@ "isComposite": false, "isPartOfComposite": false }, - { - "name": "", - "id": "daba33a1-ad0c-4742-a909-43ad1cdfbeb6", - "path": "/buttonSouth", - "interactions": "", - "processors": "", - "groups": "Gamepad", - "action": "Jump", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "603f3daf-40bd-4854-8724-93e8017f59e3", - "path": "/secondaryButton", - "interactions": "", - "processors": "", - "groups": "XR", - "action": "Jump", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "1534dc16-a6aa-499d-9c3a-22b47347b52a", - "path": "/1", - "interactions": "", - "processors": "", - "groups": "Keyboard&Mouse", - "action": "Previous", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "25060bbd-a3a6-476e-8fba-45ae484aad05", - "path": "/dpad/left", - "interactions": "", - "processors": "", - "groups": "Gamepad", - "action": "Previous", - "isComposite": false, - "isPartOfComposite": false - }, { "name": "", "id": "1c04ea5f-b012-41d1-a6f7-02e963b52893", @@ -992,36 +745,14 @@ "isComposite": false, "isPartOfComposite": false }, - { - "name": "", - "id": "b3f66d0b-7751-423f-908b-a11c5bd95930", - "path": "/buttonNorth", - "interactions": "", - "processors": "", - "groups": "Gamepad", - "action": "Interact", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "4f4649ac-64a8-4a73-af11-b3faef356a4d", - "path": "/buttonEast", - "interactions": "", - "processors": "", - "groups": "Gamepad", - "action": "Crouch", - "isComposite": false, - "isPartOfComposite": false - }, { "name": "", "id": "36e52cba-0905-478e-a818-f4bfcb9f3b9a", - "path": "/c", + "path": "/leftCtrl", "interactions": "", "processors": "", "groups": "Keyboard&Mouse", - "action": "Crouch", + "action": "Slide", "isComposite": false, "isPartOfComposite": false },