diff --git a/Game/CourierOld/Assets/Code/Configs/CharacterConfig.cs b/Game/CourierOld/Assets/Code/Configs/CharacterConfig.cs index 14124e1..6aad509 100644 --- a/Game/CourierOld/Assets/Code/Configs/CharacterConfig.cs +++ b/Game/CourierOld/Assets/Code/Configs/CharacterConfig.cs @@ -7,11 +7,15 @@ namespace Code.Configs { // Основное движение по земле public float - maxStableMoveSpeed = 8f, // Максимальная скорость движения по устойчивой поверхности - sprintMoveSpeed = 12f, // Максимальная скорость спринта + maxStableMoveSpeed = 8f, // Максимальная скорость движения по устойчивой поверхности stableMovementSharpness = 15f, // Резкость изменения скорости движения (чем выше - тем резче) - orientationSharpness = 10f, // Резкость изменения вращения персонажа (чем выше - тем резче) - jumpSpeed = 10f; // Скорость прыжка + orientationSharpness = 10f, // Резкость изменения вращения персонажа (чем выше - тем резче) + jumpSpeed = 10f; // Скорость прыжка + + // Спринт + public float + sprintMoveSpeed = 12f, // Максимальная скорость спринта + sprintAngleThreshold = 90f; // Максимальный угол (в градусах) от направления вперёд, при котором разрешён спринт // Слайд public float @@ -21,8 +25,9 @@ namespace Code.Configs // Залазание на стены public float - wallClimbSpeedFactor = 0.8f, // Коэффициент преобразования горизонтальной скорости в вертикальную при залазании на стену - minWallClimbSpeed = 9f; // Минимальная горизонтальная скорость для начала залазания на стену + wallClimbSpeedFactor = 0.8f, // Коэффициент преобразования горизонтальной скорости в вертикальную при залазании на стену + minWallClimbSpeed = 9f, // Минимальная горизонтальная скорость для начала залазания на стену + wallDetectionAngleThreshold = 80f; // Максимальный угол (в градусах) от вертикали, при котором поверхность считается "стеной" // Гравитация public Vector3 gravity = new(0f, -30f, 0f); // Вектор, отвечающий за применение гравитации diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallClimbMechanic.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallClimbMechanic.cs index decac53..96c140e 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallClimbMechanic.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallClimbMechanic.cs @@ -13,12 +13,16 @@ namespace Code.Gameplay.Character.Controller.Abilities private readonly float _wallClimbSpeedFactor; // Минимальная горизонтальная скорость для начала залазания на стену private readonly float _minWallClimbSpeed; + // Пороговый косинус стены + private readonly float _wallNormalThreshold; // Конструктор механики залазания на стену - public WallClimbMechanic(float wallClimbSpeedFactor, float minWallClimbSpeed) + public WallClimbMechanic(float wallClimbSpeedFactor, float minWallClimbSpeed, float wallDetectionAngleThreshold) { _wallClimbSpeedFactor = wallClimbSpeedFactor; _minWallClimbSpeed = minWallClimbSpeed; + // Преобразуем угол в косинус порога: если |dot| > cos(threshold), то это НЕ стена + _wallNormalThreshold = Mathf.Cos(Mathf.Deg2Rad * wallDetectionAngleThreshold); } // Обработка столкновения при движении (вызывается при ударе о препятствие) @@ -26,7 +30,7 @@ namespace Code.Gameplay.Character.Controller.Abilities { // Проверяем, что это вертикальная или почти вертикальная поверхность (стена) var dotWithUp = Vector3.Dot(hitNormal, motor.CharacterUp); - if (Mathf.Abs(dotWithUp) > 0.1f) return; // Не стена — это пол или потолок + if (Mathf.Abs(dotWithUp) > _wallNormalThreshold) return; // Не стена — это пол или потолок // Получаем текущую скорость персонажа var currentVelocity = motor.Velocity; diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs index e5bd3df..156aed6 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs @@ -35,7 +35,9 @@ namespace Code.Gameplay.Character.Controller private void Awake() { // Инициализация подсистем с параметрами из конфига - _inputHandler = new CharacterInputHandler(); + _inputHandler = new CharacterInputHandler( + _characterConfig.sprintAngleThreshold + ); _slideMechanic = new SlideMechanic( _characterConfig.slideSpeed, _characterConfig.slideDuration, @@ -43,7 +45,8 @@ namespace Code.Gameplay.Character.Controller ); _wallClimbMechanic = new WallClimbMechanic( _characterConfig.wallClimbSpeedFactor, - _characterConfig.minWallClimbSpeed + _characterConfig.minWallClimbSpeed, + _characterConfig.wallDetectionAngleThreshold ); _groundMovement = new GroundMovementSystem( _characterConfig.maxStableMoveSpeed, diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Input/CharacterInputHandler.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Input/CharacterInputHandler.cs index db722ad..a4daa1f 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Input/CharacterInputHandler.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Input/CharacterInputHandler.cs @@ -11,6 +11,9 @@ namespace Code.Gameplay.Character.Controller.Input */ public class CharacterInputHandler { + // Косинус порогового угла для спринта (предвычислен) + private readonly float _sprintAngleThresholdCos; + // Векторы движения и направления взгляда public Vector3 MoveInputVector { get; set; } public Vector3 LookInputVector { get; set; } @@ -23,7 +26,16 @@ namespace Code.Gameplay.Character.Controller.Input // Флаг-свойство указывающий, что нужно применить вращение камеры к персонажу public bool ShouldApplyCameraRotation { get; private set; } - + + // Конструктор с пороговым углом + public CharacterInputHandler(float sprintAngleThreshold) + { + // Предвычисляем косинус порогового угла для эффективности + // Угол в градусах → радианы → косинус + // Чем меньше угол — тем строже условие + _sprintAngleThresholdCos = Mathf.Cos(Mathf.Deg2Rad * sprintAngleThreshold); + } + // Обработка и преобразование входных данных от персонажа public void ProcessInputs(ref CharacterInputs inputs, KinematicCharacterMotor motor) { @@ -31,7 +43,7 @@ namespace Code.Gameplay.Character.Controller.Input var currentCameraMode = inputs.CameraMode; // Обработка спринта - IsSprinting = inputs is { SprintPressed: true, MoveAxisForward: > 0.1f }; // Спринт только при движении вперёд + IsSprinting = inputs.SprintPressed && inputs.MoveAxisForward > _sprintAngleThresholdCos; // Спринт только при движении на заданный в конфиге угол // Нормализация вектора движения и ограничение его величины до 1 var moveInputVector = diff --git a/Game/CourierOld/Assets/Resources/Configs/App/CharacterConfig.asset b/Game/CourierOld/Assets/Resources/Configs/App/CharacterConfig.asset index d25d86b..1be96eb 100644 --- a/Game/CourierOld/Assets/Resources/Configs/App/CharacterConfig.asset +++ b/Game/CourierOld/Assets/Resources/Configs/App/CharacterConfig.asset @@ -13,13 +13,15 @@ MonoBehaviour: m_Name: CharacterConfig m_EditorClassIdentifier: Assembly-CSharp::Code.Configs.CharacterConfig maxStableMoveSpeed: 8 - sprintMoveSpeed: 12 stableMovementSharpness: 15 orientationSharpness: 10 jumpSpeed: 10 + sprintMoveSpeed: 12 + sprintAngleThreshold: 90 slideSpeed: 20 slideDuration: 0.8 slideCooldown: 1.5 wallClimbSpeedFactor: 0.8 minWallClimbSpeed: 9 + wallDetectionAngleThreshold: 80 gravity: {x: 0, y: -30, z: 0}