Убран бег (просто заменён на ходьбу с такой же скоростью), прошлый слайд заменён на дэщ, добавлен новый слайд
This commit is contained in:
1 parent
a1c2c5fd18
commit
77fd9af29d
16 files changed
+247
-182
No files matched your search
@@ -5,31 +5,31 @@ namespace Code.Configs
|
|||||||
[CreateAssetMenu(fileName = "CharacterConfig", menuName = "Config/CharacterConfig")]
|
[CreateAssetMenu(fileName = "CharacterConfig", menuName = "Config/CharacterConfig")]
|
||||||
public class CharacterConfig : ScriptableObject
|
public class CharacterConfig : ScriptableObject
|
||||||
{
|
{
|
||||||
// Основное движение по земле
|
|
||||||
public float
|
public float
|
||||||
maxStableMoveSpeed = 8f, // Максимальная скорость движения по устойчивой поверхности
|
maxStableMoveSpeed = 12f,
|
||||||
stableMovementSharpness = 15f, // Резкость изменения скорости движения (чем выше - тем резче)
|
stableMovementSharpness = 15f,
|
||||||
orientationSharpness = 10f, // Резкость изменения вращения персонажа (чем выше - тем резче)
|
orientationSharpness = 10f,
|
||||||
jumpSpeed = 10f; // Скорость прыжка
|
jumpSpeed = 10f;
|
||||||
|
|
||||||
// Спринт
|
public float
|
||||||
public float
|
dashSpeed = 20f,
|
||||||
sprintMoveSpeed = 12f, // Максимальная скорость спринта
|
dashDuration = 0.35f,
|
||||||
sprintAngleThreshold = 90f; // Максимальный угол (в градусах) от направления вперёд, при котором разрешён спринт
|
dashCooldown = 1.2f;
|
||||||
|
|
||||||
|
public AnimationCurve slideVelocityCurve = new(
|
||||||
|
new Keyframe(0.0f, 1.0f),
|
||||||
|
new Keyframe(0.3f, 1.4f),
|
||||||
|
new Keyframe(1.0f, 0.2f)
|
||||||
|
);
|
||||||
|
public float
|
||||||
|
slideMinVelocityThreshold = 3f,
|
||||||
|
slideCooldown = 1.5f;
|
||||||
|
|
||||||
// Слайд
|
|
||||||
public float
|
|
||||||
slideSpeed = 20f, // Скорость слайда
|
|
||||||
slideDuration = 0.8f, // Длительность слайда в секундах
|
|
||||||
slideCooldown = 1.5f; // Время перезарядки слайда в секундах
|
|
||||||
|
|
||||||
// Наклон при залазании на стены
|
|
||||||
public float
|
public float
|
||||||
leanAngle = 25f,
|
leanAngle = 25f,
|
||||||
leanThreshold = 0.3f,
|
leanThreshold = 0.3f,
|
||||||
leanSmoothSpeed = 10f;
|
leanSmoothSpeed = 10f;
|
||||||
|
|
||||||
// Гравитация
|
public Vector3 gravity = new(0f, -30f, 0f);
|
||||||
public Vector3 gravity = new(0f, -30f, 0f); // Вектор, отвечающий за применение гравитации
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using Code.Gameplay.Camera;
|
||||||
|
using KinematicCharacterController;
|
||||||
|
|
||||||
|
namespace Code.Gameplay.Character.Controller.Abilities
|
||||||
|
{
|
||||||
|
public class DashMechanic
|
||||||
|
{
|
||||||
|
private readonly float _dashSpeed;
|
||||||
|
private readonly float _dashDuration;
|
||||||
|
private readonly float _dashCooldown;
|
||||||
|
|
||||||
|
private float _dashTimer;
|
||||||
|
private float _dashCooldownTimer;
|
||||||
|
private Vector3 _dashDirection;
|
||||||
|
private bool _dashRequested;
|
||||||
|
|
||||||
|
public bool IsDashing { get; private set; }
|
||||||
|
|
||||||
|
public DashMechanic(float dashSpeed, float dashDuration, float dashCooldown)
|
||||||
|
{
|
||||||
|
_dashSpeed = dashSpeed;
|
||||||
|
_dashDuration = dashDuration;
|
||||||
|
_dashCooldown = dashCooldown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TickCooldown(float deltaTime)
|
||||||
|
{
|
||||||
|
if (_dashCooldownTimer > 0f) _dashCooldownTimer -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestDash(bool dashPressed)
|
||||||
|
{
|
||||||
|
if (dashPressed && !_dashRequested && _dashCooldownTimer <= 0f)
|
||||||
|
_dashRequested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TryStartDash(KinematicCharacterMotor motor,
|
||||||
|
CameraMode currentCameraMode,
|
||||||
|
Quaternion firstPersonCameraRotation,
|
||||||
|
Vector3 lookInputVector)
|
||||||
|
{
|
||||||
|
if (!_dashRequested || !motor.GroundingStatus.IsStableOnGround || _dashCooldownTimer > 0f)
|
||||||
|
{
|
||||||
|
_dashRequested = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsDashing = true;
|
||||||
|
_dashTimer = _dashDuration;
|
||||||
|
|
||||||
|
var dir = currentCameraMode == CameraMode.FirstPerson
|
||||||
|
? firstPersonCameraRotation * Vector3.forward
|
||||||
|
: lookInputVector;
|
||||||
|
|
||||||
|
_dashDirection = Vector3.ProjectOnPlane(dir, motor.CharacterUp).normalized;
|
||||||
|
if (_dashDirection.sqrMagnitude < 0.01f) _dashDirection = motor.CharacterForward;
|
||||||
|
|
||||||
|
_dashCooldownTimer = _dashCooldown;
|
||||||
|
_dashRequested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleDash(ref Vector3 currentVelocity, float deltaTime, KinematicCharacterMotor motor)
|
||||||
|
{
|
||||||
|
_dashTimer -= deltaTime;
|
||||||
|
if (_dashTimer <= 0f || !motor.GroundingStatus.IsStableOnGround)
|
||||||
|
{
|
||||||
|
EndDash();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentVelocity = _dashDirection * _dashSpeed;
|
||||||
|
currentVelocity += motor.CharacterUp * 1.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndDash()
|
||||||
|
{
|
||||||
|
IsDashing = false;
|
||||||
|
_dashTimer = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6d62efb53e0c4d49be9fc658484e2575
|
||||||
|
timeCreated: 1764856437
|
||||||
+41
-72
@@ -1,122 +1,91 @@
|
|||||||
|
using UnityEngine;
|
||||||
using Code.Gameplay.Camera;
|
using Code.Gameplay.Camera;
|
||||||
using KinematicCharacterController;
|
using KinematicCharacterController;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Code.Gameplay.Character.Controller.Abilities
|
namespace Code.Gameplay.Character.Controller.Abilities
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Механика слайда для персонажа
|
|
||||||
* Отвечает за управление состоянием, таймерами и скоростью слайда
|
|
||||||
*/
|
|
||||||
public class SlideMechanic
|
public class SlideMechanic
|
||||||
{
|
{
|
||||||
// Скорость слайда
|
private readonly AnimationCurve _velocityCurve;
|
||||||
private readonly float _slideSpeed;
|
private readonly float _minVelocityThreshold;
|
||||||
// Длительность слайда в секундах
|
private readonly float _cooldown;
|
||||||
private readonly float _slideDuration;
|
|
||||||
// Время перезарядки слайда
|
|
||||||
private readonly float _slideCooldown;
|
|
||||||
|
|
||||||
// Таймер слайда
|
private float _slideTime;
|
||||||
private float _slideTimer;
|
private float _cooldownTimer;
|
||||||
// Таймер перезарядки слайда
|
|
||||||
private float _slideCooldownTimer;
|
|
||||||
// Направление слайда
|
|
||||||
private Vector3 _slideDirection;
|
private Vector3 _slideDirection;
|
||||||
// Флаг запроса слайда
|
|
||||||
private bool _slideRequested;
|
private bool _slideRequested;
|
||||||
|
private float _initialSpeed;
|
||||||
// Свойство-флаг, активен ли слайд
|
|
||||||
public bool IsSliding { get; private set; }
|
public bool IsSliding { get; private set; }
|
||||||
|
|
||||||
// Конструктор механики слайда
|
public SlideMechanic(AnimationCurve velocityCurve, float minVelocityThreshold, float cooldown)
|
||||||
public SlideMechanic(float slideSpeed, float slideDuration, float slideCooldown)
|
|
||||||
{
|
{
|
||||||
_slideSpeed = slideSpeed;
|
_velocityCurve = velocityCurve;
|
||||||
_slideDuration = slideDuration;
|
_minVelocityThreshold = minVelocityThreshold;
|
||||||
_slideCooldown = slideCooldown;
|
_cooldown = cooldown;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем таймер перезарядки слайда
|
|
||||||
public void TickCooldown(float deltaTime)
|
public void TickCooldown(float deltaTime)
|
||||||
{
|
{
|
||||||
if (_slideCooldownTimer > 0f)
|
if (_cooldownTimer > 0f) _cooldownTimer -= deltaTime;
|
||||||
{
|
|
||||||
_slideCooldownTimer -= deltaTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка слайда
|
|
||||||
public void RequestSlide(bool slidePressed)
|
public void RequestSlide(bool slidePressed)
|
||||||
{
|
{
|
||||||
if (slidePressed && !_slideRequested && _slideCooldownTimer <= 0f)
|
if (slidePressed && !_slideRequested && _cooldownTimer <= 0f)
|
||||||
{
|
|
||||||
_slideRequested = true;
|
_slideRequested = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Начало слайда
|
|
||||||
public void TryStartSlide(KinematicCharacterMotor motor,
|
public void TryStartSlide(KinematicCharacterMotor motor,
|
||||||
CameraMode currentCameraMode,
|
CameraMode currentCameraMode,
|
||||||
Quaternion firstPersonCameraRotation,
|
Quaternion firstPersonCameraRotation,
|
||||||
Vector3 lookInputVector)
|
Vector3 lookInputVector)
|
||||||
{
|
{
|
||||||
// Проверяем условия для старта слайда
|
if (!_slideRequested || !motor.GroundingStatus.IsStableOnGround || _cooldownTimer > 0f)
|
||||||
if (!_slideRequested || !motor.GroundingStatus.IsStableOnGround || _slideCooldownTimer > 0f)
|
|
||||||
{
|
{
|
||||||
_slideRequested = false;
|
_slideRequested = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IsSliding = true;
|
IsSliding = true;
|
||||||
_slideTimer = _slideDuration;
|
_slideTime = 0f;
|
||||||
|
|
||||||
// НАПРАВЛЕНИЕ СЛАЙДА - ВСЕГДА ВПЕРЕД ПО КАМЕРЕ
|
|
||||||
// Используем направление камеры, но проецируем на горизонтальную плоскость
|
|
||||||
var slideDir = currentCameraMode == CameraMode.FirstPerson ?
|
|
||||||
firstPersonCameraRotation * Vector3.forward :
|
|
||||||
lookInputVector;
|
|
||||||
|
|
||||||
// Проецируем на горизонтальную плоскость и нормализуем
|
|
||||||
_slideDirection = Vector3.ProjectOnPlane(slideDir, motor.CharacterUp).normalized;
|
|
||||||
|
|
||||||
// Если направление нулевое (персонаж стоит на месте), используем направление вперед
|
|
||||||
if (_slideDirection.sqrMagnitude < 0.01f)
|
|
||||||
{
|
|
||||||
_slideDirection = motor.CharacterForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Устанавливаем перезарядку
|
var dir = currentCameraMode == CameraMode.FirstPerson
|
||||||
_slideCooldownTimer = _slideCooldown;
|
? firstPersonCameraRotation * Vector3.forward
|
||||||
|
: lookInputVector;
|
||||||
|
|
||||||
|
_slideDirection = Vector3.ProjectOnPlane(dir, motor.CharacterUp).normalized;
|
||||||
|
if (_slideDirection.sqrMagnitude < 0.01f) _slideDirection = motor.CharacterForward;
|
||||||
|
|
||||||
|
_initialSpeed = motor.Velocity.magnitude;
|
||||||
|
if (_initialSpeed < 0.1f) _initialSpeed = 12f; // fallback
|
||||||
|
|
||||||
|
_cooldownTimer = _cooldown;
|
||||||
_slideRequested = false;
|
_slideRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка слайда
|
|
||||||
public void HandleSlide(ref Vector3 currentVelocity, float deltaTime, KinematicCharacterMotor motor)
|
public void HandleSlide(ref Vector3 currentVelocity, float deltaTime, KinematicCharacterMotor motor)
|
||||||
{
|
{
|
||||||
// Уменьшаем таймер слайда
|
if (!IsSliding) return;
|
||||||
_slideTimer -= deltaTime;
|
|
||||||
|
_slideTime += deltaTime;
|
||||||
|
|
||||||
// Если время слайда вышло, персонаж в воздухе - заканчиваем слайд
|
var t = Mathf.Clamp01(_slideTime / 2.5f);
|
||||||
if (_slideTimer <= 0f || !motor.GroundingStatus.IsStableOnGround)
|
var speedMult = _velocityCurve.Evaluate(t);
|
||||||
{
|
|
||||||
|
var targetSpeed = _initialSpeed * speedMult;
|
||||||
|
currentVelocity = _slideDirection * targetSpeed;
|
||||||
|
|
||||||
|
currentVelocity += motor.CharacterUp * 1f;
|
||||||
|
|
||||||
|
if (targetSpeed < _minVelocityThreshold || !motor.GroundingStatus.IsStableOnGround)
|
||||||
EndSlide();
|
EndSlide();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Устанавливаем скорость слайда вперед
|
|
||||||
// Используем прямую установку скорости вместо сложных вычислений
|
|
||||||
currentVelocity = _slideDirection * _slideSpeed;
|
|
||||||
|
|
||||||
// Добавляем небольшую вертикальную компоненту для лучшего скольжения по неровностям
|
|
||||||
currentVelocity += motor.CharacterUp * 2f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Завершение слайда
|
|
||||||
public void EndSlide()
|
public void EndSlide()
|
||||||
{
|
{
|
||||||
IsSliding = false;
|
IsSliding = false;
|
||||||
_slideTimer = 0f;
|
_slideTime = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+26
-24
@@ -27,6 +27,7 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
|
|
||||||
// Подсистемы
|
// Подсистемы
|
||||||
private CharacterInputHandler _inputHandler;
|
private CharacterInputHandler _inputHandler;
|
||||||
|
private DashMechanic _dashMechanic;
|
||||||
private SlideMechanic _slideMechanic;
|
private SlideMechanic _slideMechanic;
|
||||||
// private WallClimbMechanic _wallClimbMechanic;
|
// private WallClimbMechanic _wallClimbMechanic;
|
||||||
private WallRunningMechanic _wallRunningMechanic;
|
private WallRunningMechanic _wallRunningMechanic;
|
||||||
@@ -50,21 +51,20 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
{
|
{
|
||||||
_characterConfig = characterConfig;
|
_characterConfig = characterConfig;
|
||||||
// Инициализация подсистем с параметрами из конфига
|
// Инициализация подсистем с параметрами из конфига
|
||||||
_inputHandler = new CharacterInputHandler(
|
_inputHandler = new CharacterInputHandler();
|
||||||
_characterConfig.sprintAngleThreshold
|
_dashMechanic = new DashMechanic(
|
||||||
|
_characterConfig.dashSpeed,
|
||||||
|
_characterConfig.dashDuration,
|
||||||
|
_characterConfig.dashCooldown
|
||||||
);
|
);
|
||||||
_slideMechanic = new SlideMechanic(
|
_slideMechanic = new SlideMechanic(
|
||||||
_characterConfig.slideSpeed,
|
_characterConfig.slideVelocityCurve,
|
||||||
_characterConfig.slideDuration,
|
_characterConfig.slideMinVelocityThreshold,
|
||||||
_characterConfig.slideCooldown
|
_characterConfig.slideCooldown
|
||||||
);
|
);
|
||||||
// _wallClimbMechanic = new WallClimbMechanic(
|
|
||||||
// _characterConfig.wallClimbSpeedFactor,
|
|
||||||
// _characterConfig.minWallClimbSpeed,
|
|
||||||
// _characterConfig.wallDetectionAngleThreshold
|
|
||||||
// );
|
|
||||||
_wallRunningMechanic = new WallRunningMechanic();
|
_wallRunningMechanic = new WallRunningMechanic();
|
||||||
// Настройка параметров WallRunningMechanic (можно вынести в конфиг позже)
|
|
||||||
|
// TODO: WallRunningMechanic (можно вынести в конфиг позже)
|
||||||
_wallRunningMechanic.MaxWallRunTime = 1.75f;
|
_wallRunningMechanic.MaxWallRunTime = 1.75f;
|
||||||
_wallRunningMechanic.WallRunSpeed = 15.0f;
|
_wallRunningMechanic.WallRunSpeed = 15.0f;
|
||||||
_wallRunningMechanic.WallRunAcceleration = 25.0f;
|
_wallRunningMechanic.WallRunAcceleration = 25.0f;
|
||||||
@@ -79,7 +79,6 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
);
|
);
|
||||||
_groundMovement = new GroundMovementSystem(
|
_groundMovement = new GroundMovementSystem(
|
||||||
_characterConfig.maxStableMoveSpeed,
|
_characterConfig.maxStableMoveSpeed,
|
||||||
_characterConfig.sprintMoveSpeed,
|
|
||||||
_characterConfig.stableMovementSharpness,
|
_characterConfig.stableMovementSharpness,
|
||||||
_characterConfig.jumpSpeed
|
_characterConfig.jumpSpeed
|
||||||
);
|
);
|
||||||
@@ -99,17 +98,15 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
public void SetInputs(ref CharacterInputs inputs)
|
public void SetInputs(ref CharacterInputs inputs)
|
||||||
{
|
{
|
||||||
_lastInputs = inputs;
|
_lastInputs = inputs;
|
||||||
// Обновляем таймеры механик
|
_dashMechanic.TickCooldown(Time.deltaTime);
|
||||||
_slideMechanic.TickCooldown(Time.deltaTime);
|
_slideMechanic.TickCooldown(Time.deltaTime);
|
||||||
// _wallClimbMechanic.TickCooldown(Time.deltaTime);
|
|
||||||
_wallRunningMechanic.Tick(Time.deltaTime);
|
_wallRunningMechanic.Tick(Time.deltaTime);
|
||||||
|
|
||||||
// Если активен слайд - игнорируем весь остальной ввод
|
// Если активен слайд - игнорируем весь остальной ввод
|
||||||
if (_slideMechanic.IsSliding)
|
if (_dashMechanic.IsDashing || _slideMechanic.IsSliding)
|
||||||
{
|
{
|
||||||
_inputHandler.MoveInputVector = Vector3.zero;
|
_inputHandler.MoveInputVector = Vector3.zero;
|
||||||
_inputHandler.LookInputVector = Vector3.one;
|
_inputHandler.LookInputVector = Vector3.one;
|
||||||
_inputHandler.IsSprinting = false;
|
|
||||||
_groundMovement.RequestJump(inputs.JumpPressed);
|
_groundMovement.RequestJump(inputs.JumpPressed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -125,12 +122,12 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inputs.SprintPressed = false;
|
inputs.DashPressed = false;
|
||||||
inputs.SlidePressed = false;
|
inputs.SlidePressed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка слайда
|
_dashMechanic.RequestDash(inputs.DashPressed);
|
||||||
_slideMechanic.RequestSlide(inputs.SlidePressed);
|
_slideMechanic.RequestSlide(inputs.SlidePressed);
|
||||||
|
|
||||||
// Обработка остального ввода
|
// Обработка остального ввода
|
||||||
@@ -172,16 +169,21 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
|
|
||||||
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (_dashMechanic.IsDashing && _groundMovement.JumpRequested)
|
||||||
|
_dashMechanic.EndDash();
|
||||||
if (_slideMechanic.IsSliding && _groundMovement.JumpRequested)
|
if (_slideMechanic.IsSliding && _groundMovement.JumpRequested)
|
||||||
{
|
|
||||||
_slideMechanic.EndSlide();
|
_slideMechanic.EndSlide();
|
||||||
|
|
||||||
|
if (!_dashMechanic.IsDashing)
|
||||||
|
_dashMechanic.TryStartDash(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation, _inputHandler.LookInputVector);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dashMechanic.HandleDash(ref currentVelocity, deltaTime, motor);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_slideMechanic.IsSliding)
|
if (!_slideMechanic.IsSliding)
|
||||||
{
|
_slideMechanic.TryStartSlide(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation, _inputHandler.LookInputVector);
|
||||||
_slideMechanic.TryStartSlide(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation,
|
|
||||||
_inputHandler.LookInputVector);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_slideMechanic.HandleSlide(ref currentVelocity, deltaTime, motor);
|
_slideMechanic.HandleSlide(ref currentVelocity, deltaTime, motor);
|
||||||
@@ -229,10 +231,10 @@ namespace Code.Gameplay.Character.Controller
|
|||||||
|
|
||||||
public void PostGroundingUpdate(float deltaTime)
|
public void PostGroundingUpdate(float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (_dashMechanic.IsDashing && !motor.GroundingStatus.IsStableOnGround)
|
||||||
|
_dashMechanic.EndDash();
|
||||||
if (_slideMechanic.IsSliding && !motor.GroundingStatus.IsStableOnGround)
|
if (_slideMechanic.IsSliding && !motor.GroundingStatus.IsStableOnGround)
|
||||||
{
|
|
||||||
_slideMechanic.EndSlide();
|
_slideMechanic.EndSlide();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AfterCharacterUpdate(float deltaTime)
|
public void AfterCharacterUpdate(float deltaTime)
|
||||||
|
|||||||
+1
-18
@@ -11,40 +11,23 @@ namespace Code.Gameplay.Character.Controller.Input
|
|||||||
*/
|
*/
|
||||||
public class CharacterInputHandler
|
public class CharacterInputHandler
|
||||||
{
|
{
|
||||||
// Косинус порогового угла для спринта (предвычислен)
|
|
||||||
private readonly float _sprintAngleThresholdCos;
|
|
||||||
|
|
||||||
// Векторы движения и направления взгляда
|
// Векторы движения и направления взгляда
|
||||||
public Vector3 MoveInputVector { get; set; }
|
public Vector3 MoveInputVector { get; set; }
|
||||||
public Vector3 LookInputVector { get; set; }
|
public Vector3 LookInputVector { get; set; }
|
||||||
|
|
||||||
// Флаг-свойство указывающий, что активен режим спринта
|
|
||||||
public bool IsSprinting { get; set; }
|
|
||||||
|
|
||||||
// Вращение камеры в FirstPerson режиме для синхронизации (только горизонтальная компонента)
|
// Вращение камеры в FirstPerson режиме для синхронизации (только горизонтальная компонента)
|
||||||
public Quaternion FirstPersonCameraRotation { get; set; }
|
public Quaternion FirstPersonCameraRotation { get; set; }
|
||||||
|
|
||||||
// Флаг-свойство указывающий, что нужно применить вращение камеры к персонажу
|
// Флаг-свойство указывающий, что нужно применить вращение камеры к персонажу
|
||||||
public bool ShouldApplyCameraRotation { get; private set; }
|
public bool ShouldApplyCameraRotation { get; private set; }
|
||||||
|
|
||||||
// Конструктор с пороговым углом
|
|
||||||
public CharacterInputHandler(float sprintAngleThreshold)
|
|
||||||
{
|
|
||||||
// Предвычисляем косинус порогового угла для эффективности
|
|
||||||
// Угол в градусах → радианы → косинус
|
|
||||||
// Чем меньше угол — тем строже условие
|
|
||||||
_sprintAngleThresholdCos = Mathf.Cos(Mathf.Deg2Rad * sprintAngleThreshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка и преобразование входных данных от персонажа
|
// Обработка и преобразование входных данных от персонажа
|
||||||
public void ProcessInputs(ref CharacterInputs inputs, KinematicCharacterMotor motor)
|
public void ProcessInputs(ref CharacterInputs inputs, KinematicCharacterMotor motor)
|
||||||
{
|
{
|
||||||
// Сохраняем текущий режим камеры
|
// Сохраняем текущий режим камеры
|
||||||
var currentCameraMode = inputs.CameraMode;
|
var currentCameraMode = inputs.CameraMode;
|
||||||
|
|
||||||
// Обработка спринта
|
|
||||||
IsSprinting = inputs.SprintPressed && inputs.MoveAxisForward > _sprintAngleThresholdCos; // Спринт только при движении на заданный в конфиге угол
|
|
||||||
|
|
||||||
// Нормализация вектора движения и ограничение его величины до 1
|
// Нормализация вектора движения и ограничение его величины до 1
|
||||||
var moveInputVector =
|
var moveInputVector =
|
||||||
Vector3.ClampMagnitude(new Vector3(inputs.MoveAxisRight, 0, inputs.MoveAxisForward), 1f);
|
Vector3.ClampMagnitude(new Vector3(inputs.MoveAxisRight, 0, inputs.MoveAxisForward), 1f);
|
||||||
|
|||||||
+2
-6
@@ -11,8 +11,6 @@ namespace Code.Gameplay.Character.Controller.Movement
|
|||||||
{
|
{
|
||||||
// Максимальная скорость движения по устойчивой поверхности
|
// Максимальная скорость движения по устойчивой поверхности
|
||||||
private readonly float _maxStableMoveSpeed;
|
private readonly float _maxStableMoveSpeed;
|
||||||
// Максимальная скорость спринта
|
|
||||||
private readonly float _sprintMoveSpeed;
|
|
||||||
// Резкость изменения скорости движения (чем выше - тем резче)
|
// Резкость изменения скорости движения (чем выше - тем резче)
|
||||||
private readonly float _stableMovementSharpness;
|
private readonly float _stableMovementSharpness;
|
||||||
// Скорость прыжка
|
// Скорость прыжка
|
||||||
@@ -22,10 +20,9 @@ namespace Code.Gameplay.Character.Controller.Movement
|
|||||||
public bool JumpRequested { get; private set; }
|
public bool JumpRequested { get; private set; }
|
||||||
|
|
||||||
// Конструктор системы движения на земле
|
// Конструктор системы движения на земле
|
||||||
public GroundMovementSystem(float maxStableMoveSpeed, float sprintMoveSpeed, float stableMovementSharpness, float jumpSpeed)
|
public GroundMovementSystem(float maxStableMoveSpeed, float stableMovementSharpness, float jumpSpeed)
|
||||||
{
|
{
|
||||||
_maxStableMoveSpeed = maxStableMoveSpeed;
|
_maxStableMoveSpeed = maxStableMoveSpeed;
|
||||||
_sprintMoveSpeed = sprintMoveSpeed;
|
|
||||||
_stableMovementSharpness = stableMovementSharpness;
|
_stableMovementSharpness = stableMovementSharpness;
|
||||||
_jumpSpeed = jumpSpeed;
|
_jumpSpeed = jumpSpeed;
|
||||||
}
|
}
|
||||||
@@ -66,8 +63,7 @@ namespace Code.Gameplay.Character.Controller.Movement
|
|||||||
inputHandler.MoveInputVector.magnitude;
|
inputHandler.MoveInputVector.magnitude;
|
||||||
|
|
||||||
// Расчет целевой скорости движения с учетом ограничения максимальной скорости и спринта
|
// Расчет целевой скорости движения с учетом ограничения максимальной скорости и спринта
|
||||||
var targetSpeed = inputHandler.IsSprinting ? _sprintMoveSpeed : _maxStableMoveSpeed;
|
var targetMovementVelocity = reorientedInput * _maxStableMoveSpeed;
|
||||||
var targetMovementVelocity = reorientedInput * targetSpeed;
|
|
||||||
|
|
||||||
// Плавная интерполяция текущей скорости к целевой с экспоненциальным сглаживанием
|
// Плавная интерполяция текущей скорости к целевой с экспоненциальным сглаживанием
|
||||||
currentVelocity = Vector3.Lerp(
|
currentVelocity = Vector3.Lerp(
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ namespace Code.Gameplay.Character.Core
|
|||||||
inputs.MoveAxisForward = moveInput.y; // Vertical ось (W/S или Up/Down)
|
inputs.MoveAxisForward = moveInput.y; // Vertical ось (W/S или Up/Down)
|
||||||
inputs.MoveAxisRight = moveInput.x; // Horizontal ось (A/D или Left/Right)
|
inputs.MoveAxisRight = moveInput.x; // Horizontal ось (A/D или Left/Right)
|
||||||
inputs.JumpPressed = _inputService.JumpPressed; // Прыжки (Space)
|
inputs.JumpPressed = _inputService.JumpPressed; // Прыжки (Space)
|
||||||
inputs.SprintPressed = _inputService.SprintPressed; // Спринт (Shift)
|
|
||||||
inputs.SlidePressed = _inputService.SlidePressed; // Слайд (Ctrl)
|
inputs.SlidePressed = _inputService.SlidePressed; // Слайд (Ctrl)
|
||||||
|
inputs.DashPressed = _inputService.DashPressed; // Слайд (Ctrl)
|
||||||
inputs.CameraMode = ((ICameraState)_cameraStateMachine.CurrentBaseState).GetCameraMode();
|
inputs.CameraMode = ((ICameraState)_cameraStateMachine.CurrentBaseState).GetCameraMode();
|
||||||
|
|
||||||
// Передаем информацию о камере для адаптивного поведения
|
// Передаем информацию о камере для адаптивного поведения
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Code.Gameplay.Character.Core
|
|||||||
public CameraMode CameraMode; // Текущий режим камеры для адаптации поведения
|
public CameraMode CameraMode; // Текущий режим камеры для адаптации поведения
|
||||||
public Vector3 CameraPlanarDirection; // Направление камеры в горизонтальной плоскости
|
public Vector3 CameraPlanarDirection; // Направление камеры в горизонтальной плоскости
|
||||||
public bool JumpPressed; // Флаг указывающий, нажата ли кнопка прыжка
|
public bool JumpPressed; // Флаг указывающий, нажата ли кнопка прыжка
|
||||||
public bool SprintPressed; // Флаг указывающий, нажата ли кнопка спринта
|
public bool DashPressed;
|
||||||
public bool SlidePressed; // Флаг указывающий, нажата ли кнопка слайда
|
public bool SlidePressed; // Флаг указывающий, нажата ли кнопка слайда
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ namespace Code.Gameplay.Character.Core
|
|||||||
inputs.MoveAxisForward = moveInput.y; // Vertical ось (W/S или Up/Down)
|
inputs.MoveAxisForward = moveInput.y; // Vertical ось (W/S или Up/Down)
|
||||||
inputs.MoveAxisRight = moveInput.x; // Horizontal ось (A/D или Left/Right)
|
inputs.MoveAxisRight = moveInput.x; // Horizontal ось (A/D или Left/Right)
|
||||||
inputs.JumpPressed = _inputService.JumpPressed; // Прыжки (Space)
|
inputs.JumpPressed = _inputService.JumpPressed; // Прыжки (Space)
|
||||||
inputs.SprintPressed = true;//_inputService.SprintPressed; // Спринт (Shift)
|
inputs.DashPressed = _inputService.DashPressed;
|
||||||
inputs.SlidePressed = _inputService.SlidePressed; // Слайд (Ctrl)
|
inputs.SlidePressed = _inputService.SlidePressed; // Слайд (Ctrl)
|
||||||
inputs.CameraMode = ((ICameraState)_cameraStateMachine.CurrentBaseState).GetCameraMode();
|
inputs.CameraMode = ((ICameraState)_cameraStateMachine.CurrentBaseState).GetCameraMode();
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ namespace Code.Input
|
|||||||
// Для управления движением персонажа
|
// Для управления движением персонажа
|
||||||
Vector2 MoveInput { get; }
|
Vector2 MoveInput { get; }
|
||||||
bool JumpPressed { get; }
|
bool JumpPressed { get; }
|
||||||
bool SprintPressed { get; }
|
|
||||||
bool SlidePressed { get; }
|
bool SlidePressed { get; }
|
||||||
|
bool DashPressed { get; }
|
||||||
|
|
||||||
// Для переключения режима камеры
|
// Для переключения режима камеры
|
||||||
bool ToggleCameraModePressed { get; }
|
bool ToggleCameraModePressed { get; }
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace Code.Input
|
|||||||
public float ZoomInput { get; private set; }
|
public float ZoomInput { get; private set; }
|
||||||
public Vector2 MoveInput { get; private set; }
|
public Vector2 MoveInput { get; private set; }
|
||||||
public bool JumpPressed { get; private set; }
|
public bool JumpPressed { get; private set; }
|
||||||
public bool SprintPressed { get; private set; }
|
|
||||||
public bool SlidePressed { get; private set; }
|
public bool SlidePressed { get; private set; }
|
||||||
|
public bool DashPressed { get; private set; }
|
||||||
public bool ToggleCameraModePressed { get; private set; }
|
public bool ToggleCameraModePressed { get; private set; }
|
||||||
|
|
||||||
public InputService(InputActionAsset inputActionAsset)
|
public InputService(InputActionAsset inputActionAsset)
|
||||||
@@ -69,14 +69,6 @@ namespace Code.Input
|
|||||||
jumpAction.canceled += OnJumpCanceled;
|
jumpAction.canceled += OnJumpCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка спринта (персонаж)
|
|
||||||
var sprintAction = gameplayMap.FindAction("Sprint");
|
|
||||||
if (sprintAction != null)
|
|
||||||
{
|
|
||||||
sprintAction.performed += OnSprintPerformed;
|
|
||||||
sprintAction.canceled += OnSprintCanceled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка слайда (персонаж)
|
// Обработка слайда (персонаж)
|
||||||
var slideAction = gameplayMap.FindAction("Slide");
|
var slideAction = gameplayMap.FindAction("Slide");
|
||||||
if (slideAction != null)
|
if (slideAction != null)
|
||||||
@@ -85,6 +77,14 @@ namespace Code.Input
|
|||||||
slideAction.canceled += OnSlideCanceled;
|
slideAction.canceled += OnSlideCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Обработка слайда (персонаж)
|
||||||
|
var dashAction = gameplayMap.FindAction("Dash");
|
||||||
|
if (dashAction != null)
|
||||||
|
{
|
||||||
|
dashAction.performed += OnDashPerformed;
|
||||||
|
dashAction.canceled += OnDashCanceled;
|
||||||
|
}
|
||||||
|
|
||||||
// Обработка переключения режима камеры
|
// Обработка переключения режима камеры
|
||||||
var toggleCameraModeAction = gameplayMap.FindAction("ToggleCameraMode");
|
var toggleCameraModeAction = gameplayMap.FindAction("ToggleCameraMode");
|
||||||
if (toggleCameraModeAction != null)
|
if (toggleCameraModeAction != null)
|
||||||
@@ -134,16 +134,6 @@ namespace Code.Input
|
|||||||
JumpPressed = false;
|
JumpPressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSprintPerformed(InputAction.CallbackContext context)
|
|
||||||
{
|
|
||||||
SprintPressed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSprintCanceled(InputAction.CallbackContext context)
|
|
||||||
{
|
|
||||||
SprintPressed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlidePerformed(InputAction.CallbackContext context)
|
private void OnSlidePerformed(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
SlidePressed = true;
|
SlidePressed = true;
|
||||||
@@ -154,6 +144,16 @@ namespace Code.Input
|
|||||||
SlidePressed = false;
|
SlidePressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDashPerformed(InputAction.CallbackContext context)
|
||||||
|
{
|
||||||
|
DashPressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDashCanceled(InputAction.CallbackContext context)
|
||||||
|
{
|
||||||
|
DashPressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnToggleCameraModePerformed(InputAction.CallbackContext context)
|
private void OnToggleCameraModePerformed(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
ToggleCameraModePressed = true;
|
ToggleCameraModePressed = true;
|
||||||
@@ -189,12 +189,12 @@ namespace Code.Input
|
|||||||
gameplayMap.FindAction("Jump").performed -= OnJumpPerformed;
|
gameplayMap.FindAction("Jump").performed -= OnJumpPerformed;
|
||||||
gameplayMap.FindAction("Jump").canceled -= OnJumpCanceled;
|
gameplayMap.FindAction("Jump").canceled -= OnJumpCanceled;
|
||||||
|
|
||||||
gameplayMap.FindAction("Sprint").performed -= OnSprintPerformed;
|
|
||||||
gameplayMap.FindAction("Sprint").canceled -= OnSprintCanceled;
|
|
||||||
|
|
||||||
gameplayMap.FindAction("Slide").performed -= OnSlidePerformed;
|
gameplayMap.FindAction("Slide").performed -= OnSlidePerformed;
|
||||||
gameplayMap.FindAction("Slide").canceled -= OnSlideCanceled;
|
gameplayMap.FindAction("Slide").canceled -= OnSlideCanceled;
|
||||||
|
|
||||||
|
gameplayMap.FindAction("Dash").performed -= OnDashPerformed;
|
||||||
|
gameplayMap.FindAction("Dash").canceled -= OnDashCanceled;
|
||||||
|
|
||||||
gameplayMap.FindAction("ToggleCameraMode").performed -= OnToggleCameraModePerformed;
|
gameplayMap.FindAction("ToggleCameraMode").performed -= OnToggleCameraModePerformed;
|
||||||
gameplayMap.FindAction("ToggleCameraMode").canceled -= OnToggleCameraModeCanceled;
|
gameplayMap.FindAction("ToggleCameraMode").canceled -= OnToggleCameraModeCanceled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,49 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 10cfaf8e57f64eddb8c2eda147e4739a, type: 3}
|
m_Script: {fileID: 11500000, guid: 10cfaf8e57f64eddb8c2eda147e4739a, type: 3}
|
||||||
m_Name: CharacterConfig
|
m_Name: CharacterConfig
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Code.Configs.CharacterConfig
|
m_EditorClassIdentifier: Assembly-CSharp::Code.Configs.CharacterConfig
|
||||||
maxStableMoveSpeed: 8
|
maxStableMoveSpeed: 12
|
||||||
stableMovementSharpness: 15
|
stableMovementSharpness: 15
|
||||||
orientationSharpness: 10
|
orientationSharpness: 10
|
||||||
jumpSpeed: 10
|
jumpSpeed: 10
|
||||||
sprintMoveSpeed: 12
|
dashSpeed: 20
|
||||||
sprintAngleThreshold: 90
|
dashDuration: 0.35
|
||||||
slideSpeed: 20
|
dashCooldown: 1.2
|
||||||
slideDuration: 0.8
|
slideVelocityCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0
|
||||||
|
outWeight: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0.3
|
||||||
|
value: 1.4
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0
|
||||||
|
outWeight: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 1
|
||||||
|
value: 0.2
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0
|
||||||
|
outWeight: 0
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
slideMinVelocityThreshold: 3
|
||||||
slideCooldown: 1.5
|
slideCooldown: 1.5
|
||||||
wallClimbSpeedFactor: 0.8
|
leanAngle: 25
|
||||||
minWallClimbSpeed: 9
|
leanThreshold: 0.3
|
||||||
wallDetectionAngleThreshold: 80
|
leanSmoothSpeed: 10
|
||||||
maxWallLeanAngle: 90
|
|
||||||
wallLeanSharpness: 100
|
|
||||||
wallLeanHeightScale: 0.1
|
|
||||||
gravity: {x: 0, y: -30, z: 0}
|
gravity: {x: 0, y: -30, z: 0}
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
"initialStateCheck": false
|
"initialStateCheck": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Sprint",
|
"name": "Dash",
|
||||||
"type": "Button",
|
"type": "Button",
|
||||||
"id": "641cd816-40e6-41b4-8c3d-04687c349290",
|
"id": "641cd816-40e6-41b4-8c3d-04687c349290",
|
||||||
"expectedControlType": "",
|
"expectedControlType": "",
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
"interactions": "",
|
"interactions": "",
|
||||||
"processors": "",
|
"processors": "",
|
||||||
"groups": "Keyboard&Mouse",
|
"groups": "Keyboard&Mouse",
|
||||||
"action": "Sprint",
|
"action": "Dash",
|
||||||
"isComposite": false,
|
"isComposite": false,
|
||||||
"isPartOfComposite": false
|
"isPartOfComposite": false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"hash": "e644f1bb8ea190157aaea9c386f85cee4cd03bd9"
|
"hash": "e644f1bb8ea190157aaea9c386f85cee4cd03bd9"
|
||||||
},
|
},
|
||||||
"com.unity.addressables": {
|
"com.unity.addressables": {
|
||||||
"version": "2.7.4",
|
"version": "2.7.6",
|
||||||
"depth": 2,
|
"depth": 2,
|
||||||
"source": "registry",
|
"source": "registry",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"com.unity.modules.jsonserialize": "1.0.0",
|
"com.unity.modules.jsonserialize": "1.0.0",
|
||||||
"com.unity.modules.imageconversion": "1.0.0",
|
"com.unity.modules.imageconversion": "1.0.0",
|
||||||
"com.unity.modules.unitywebrequest": "1.0.0",
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
"com.unity.scriptablebuildpipeline": "2.4.3",
|
"com.unity.scriptablebuildpipeline": "2.5.0",
|
||||||
"com.unity.modules.unitywebrequestassetbundle": "1.0.0"
|
"com.unity.modules.unitywebrequestassetbundle": "1.0.0"
|
||||||
},
|
},
|
||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"com.unity.scriptablebuildpipeline": {
|
"com.unity.scriptablebuildpipeline": {
|
||||||
"version": "2.4.3",
|
"version": "2.5.0",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"source": "registry",
|
"source": "registry",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
m_EditorVersion: 6000.2.14f1
|
m_EditorVersion: 6000.2.15f1
|
||||||
m_EditorVersionWithRevision: 6000.2.14f1 (589824c1fc31)
|
m_EditorVersionWithRevision: 6000.2.15f1 (0707b6d1e918)
|
||||||
Reference in new issue
Block a user