89 lines
4.2 KiB
C#
89 lines
4.2 KiB
C#
using UnityEngine;
|
|
using Code.Gameplay.Character.Controller.Input;
|
|
using KinematicCharacterController;
|
|
|
|
namespace Code.Gameplay.Character.Controller.Movement
|
|
{
|
|
/*
|
|
* Система движения персонажа по устойчивой поверхности
|
|
*/
|
|
public class GroundMovementSystem
|
|
{
|
|
// Максимальная скорость движения по устойчивой поверхности
|
|
private readonly float _maxStableMoveSpeed;
|
|
// Резкость изменения скорости движения (чем выше - тем резче)
|
|
private readonly float _stableMovementSharpness;
|
|
// Скорость прыжка
|
|
private readonly float _jumpSpeed;
|
|
|
|
// Свойство-флаг указывающий, что был запрошен прыжок
|
|
public bool JumpRequested { get; private set; }
|
|
|
|
// Конструктор системы движения на земле
|
|
public GroundMovementSystem(float maxStableMoveSpeed, float stableMovementSharpness, float jumpSpeed)
|
|
{
|
|
_maxStableMoveSpeed = maxStableMoveSpeed;
|
|
_stableMovementSharpness = stableMovementSharpness;
|
|
_jumpSpeed = jumpSpeed;
|
|
}
|
|
|
|
// Метод для установки запроса на прыжок извне
|
|
public void RequestJump(bool jumpPressed)
|
|
{
|
|
if (jumpPressed)
|
|
JumpRequested = true;
|
|
}
|
|
|
|
// Метод для отмены запроса на прыжок извне
|
|
public void CancelJumpRequest()
|
|
{
|
|
JumpRequested = false;
|
|
}
|
|
|
|
// Обновление скорости движения персонажа на земле
|
|
public void UpdateVelocity(
|
|
ref Vector3 currentVelocity,
|
|
CharacterInputHandler inputHandler,
|
|
KinematicCharacterMotor motor,
|
|
float deltaTime)
|
|
{
|
|
// Сохранение текущей величины скорости
|
|
var currentVelocityMagnitude = currentVelocity.magnitude;
|
|
|
|
// Получение нормали поверхности для корректного движения по наклонным плоскостям
|
|
var effectiveGroundNormal = motor.GroundingStatus.GroundNormal;
|
|
|
|
// Переориентация текущей скорости вдоль поверхности
|
|
currentVelocity = motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) *
|
|
currentVelocityMagnitude;
|
|
|
|
// Переориентация входного вектора движения вдоль поверхности
|
|
var inputRight = Vector3.Cross(inputHandler.MoveInputVector, motor.CharacterUp);
|
|
var reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized *
|
|
inputHandler.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();
|
|
|
|
if (motor.CharacterController is CustomCharacterController controller)
|
|
{
|
|
controller.TriggerJump();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |