Files
CourierOld/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Movement/GroundMovementSystem.cs
T

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();
}
}
}
}
}