122 lines
4.9 KiB
C#
122 lines
4.9 KiB
C#
using Code.Gameplay.Camera;
|
|
using KinematicCharacterController;
|
|
using UnityEngine;
|
|
|
|
namespace Code.Gameplay.Character.Controller.Abilities
|
|
{
|
|
/*
|
|
* Механика слайда для персонажа
|
|
* Отвечает за управление состоянием, таймерами и скоростью слайда
|
|
*/
|
|
public class SlideMechanic
|
|
{
|
|
// Скорость слайда
|
|
private readonly float _slideSpeed;
|
|
// Длительность слайда в секундах
|
|
private readonly float _slideDuration;
|
|
// Время перезарядки слайда
|
|
private readonly float _slideCooldown;
|
|
|
|
// Таймер слайда
|
|
private float _slideTimer;
|
|
// Таймер перезарядки слайда
|
|
private float _slideCooldownTimer;
|
|
// Направление слайда
|
|
private Vector3 _slideDirection;
|
|
// Флаг запроса слайда
|
|
private bool _slideRequested;
|
|
|
|
// Свойство-флаг, активен ли слайд
|
|
public bool IsSliding { get; private set; }
|
|
|
|
// Конструктор механики слайда
|
|
public SlideMechanic(float slideSpeed, float slideDuration, float slideCooldown)
|
|
{
|
|
_slideSpeed = slideSpeed;
|
|
_slideDuration = slideDuration;
|
|
_slideCooldown = slideCooldown;
|
|
}
|
|
|
|
// Обновляем таймер перезарядки слайда
|
|
public void TickCooldown(float deltaTime)
|
|
{
|
|
if (_slideCooldownTimer > 0f)
|
|
{
|
|
_slideCooldownTimer -= deltaTime;
|
|
}
|
|
}
|
|
|
|
// Обработка слайда
|
|
public void RequestSlide(bool slidePressed)
|
|
{
|
|
if (slidePressed && !_slideRequested && _slideCooldownTimer <= 0f)
|
|
{
|
|
_slideRequested = true;
|
|
}
|
|
}
|
|
|
|
// Начало слайда
|
|
public void TryStartSlide(KinematicCharacterMotor motor,
|
|
CameraMode currentCameraMode,
|
|
Quaternion firstPersonCameraRotation,
|
|
Vector3 lookInputVector)
|
|
{
|
|
// Проверяем условия для старта слайда
|
|
if (!_slideRequested || !motor.GroundingStatus.IsStableOnGround || _slideCooldownTimer > 0f)
|
|
{
|
|
_slideRequested = false;
|
|
return;
|
|
}
|
|
|
|
IsSliding = true;
|
|
_slideTimer = _slideDuration;
|
|
|
|
// НАПРАВЛЕНИЕ СЛАЙДА - ВСЕГДА ВПЕРЕД ПО КАМЕРЕ
|
|
// Используем направление камеры, но проецируем на горизонтальную плоскость
|
|
var slideDir = currentCameraMode == CameraMode.FirstPerson ?
|
|
firstPersonCameraRotation * Vector3.forward :
|
|
lookInputVector;
|
|
|
|
// Проецируем на горизонтальную плоскость и нормализуем
|
|
_slideDirection = Vector3.ProjectOnPlane(slideDir, motor.CharacterUp).normalized;
|
|
|
|
// Если направление нулевое (персонаж стоит на месте), используем направление вперед
|
|
if (_slideDirection.sqrMagnitude < 0.01f)
|
|
{
|
|
_slideDirection = motor.CharacterForward;
|
|
}
|
|
|
|
// Устанавливаем перезарядку
|
|
_slideCooldownTimer = _slideCooldown;
|
|
_slideRequested = false;
|
|
}
|
|
|
|
// Обработка слайда
|
|
public void HandleSlide(ref Vector3 currentVelocity, float deltaTime, KinematicCharacterMotor motor)
|
|
{
|
|
// Уменьшаем таймер слайда
|
|
_slideTimer -= deltaTime;
|
|
|
|
// Если время слайда вышло, персонаж в воздухе - заканчиваем слайд
|
|
if (_slideTimer <= 0f || !motor.GroundingStatus.IsStableOnGround)
|
|
{
|
|
EndSlide();
|
|
return;
|
|
}
|
|
|
|
// Устанавливаем скорость слайда вперед
|
|
// Используем прямую установку скорости вместо сложных вычислений
|
|
currentVelocity = _slideDirection * _slideSpeed;
|
|
|
|
// Добавляем небольшую вертикальную компоненту для лучшего скольжения по неровностям
|
|
currentVelocity += motor.CharacterUp * 2f;
|
|
}
|
|
|
|
// Завершение слайда
|
|
public void EndSlide()
|
|
{
|
|
IsSliding = false;
|
|
_slideTimer = 0f;
|
|
}
|
|
}
|
|
} |