инишиал титан падать второй мувмент (но пока очень говно)

This commit is contained in:
MrTorex committed 2025-11-27 20:37:16 +03:00
1 parent 7130513471
commit b271042137
7 files changed
+230 -1024

No files matched your search

@@ -15,7 +15,7 @@ namespace Code.Gameplay.Character.Controller
* Реализует физическое движение персонажа с использованием Kinematic Character Controller
* Обрабатывает ввод пользователя, применяет движение и вращение с учетом поверхности
*
* Источник: Tvtig, https://www.youtube.com/watch?v=9ibpY64wBYM
* Источник: Tvtig, https://www.youtube.com/watch?v=9ibpY64wBYM
*/
public class CustomCharacterController : MonoBehaviour, ICharacterController
{
@@ -28,49 +28,23 @@ namespace Code.Gameplay.Character.Controller
// Подсистемы
private CharacterInputHandler _inputHandler;
private SlideMechanic _slideMechanic;
private WallClimbMechanic _wallClimbMechanic;
// private WallClimbMechanic _wallClimbMechanic;
private WallRunningMechanic _wallRunningMechanic;
private WallLeanMechanic _wallLeanMechanic;
private GroundMovementSystem _groundMovement;
private AirMovementSystem _airMovement;
public bool IsSliding => _slideMechanic.IsSliding;
public bool IsWallRunning => _wallRunningMechanic.IsWallRunning;
private float abilityBlockTimer;
private bool isAbilitiesBlocked;
private CharacterInputs _lastInputs;
public void SetPosition(Vector3 position) => motor.SetPosition(position);
public void SetRotation(Quaternion rotation) => motor.SetRotation(rotation);
// Инициализация контроллера
// private void Awake()
// {
// // Инициализация подсистем с параметрами из конфига
// _inputHandler = new CharacterInputHandler(
// _characterConfig.sprintAngleThreshold
// );
// _slideMechanic = new SlideMechanic(
// _characterConfig.slideSpeed,
// _characterConfig.slideDuration,
// _characterConfig.slideCooldown
// );
// _wallClimbMechanic = new WallClimbMechanic(
// _characterConfig.wallClimbSpeedFactor,
// _characterConfig.minWallClimbSpeed,
// _characterConfig.wallDetectionAngleThreshold
// );
// _wallLeanMechanic = new WallLeanMechanic(
// _characterConfig.maxWallLeanAngle,
// _characterConfig.wallLeanSharpness,
// _characterConfig.wallLeanHeightScale
// );
// _groundMovement = new GroundMovementSystem(
// _characterConfig.maxStableMoveSpeed,
// _characterConfig.sprintMoveSpeed,
// _characterConfig.stableMovementSharpness,
// _characterConfig.jumpSpeed
// );
// _airMovement = new AirMovementSystem(_characterConfig.gravity);
// }
[Inject]
private void Construct(CharacterConfig characterConfig)
{
@@ -84,11 +58,20 @@ namespace Code.Gameplay.Character.Controller
_characterConfig.slideDuration,
_characterConfig.slideCooldown
);
_wallClimbMechanic = new WallClimbMechanic(
_characterConfig.wallClimbSpeedFactor,
_characterConfig.minWallClimbSpeed,
_characterConfig.wallDetectionAngleThreshold
);
// _wallClimbMechanic = new WallClimbMechanic(
// _characterConfig.wallClimbSpeedFactor,
// _characterConfig.minWallClimbSpeed,
// _characterConfig.wallDetectionAngleThreshold
// );
_wallRunningMechanic = new WallRunningMechanic();
// Настройка параметров WallRunningMechanic (можно вынести в конфиг позже)
_wallRunningMechanic.MaxWallRunTime = 1.75f;
_wallRunningMechanic.WallRunSpeed = 8.0f;
_wallRunningMechanic.WallRunAcceleration = 25.0f;
_wallRunningMechanic.WallRunGravityScale = 0.25f;
_wallRunningMechanic.WallDetachImpulse = 7.0f;
_wallRunningMechanic.WallContactAngleThreshold = 45.0f;
_wallLeanMechanic = new WallLeanMechanic(
_characterConfig.maxWallLeanAngle,
_characterConfig.wallLeanSharpness,
@@ -107,30 +90,23 @@ namespace Code.Gameplay.Character.Controller
_inputHandler.FirstPersonCameraRotation =
motor.Transform.rotation; // Начальное вращение совпадает с персонажемс
_wallLeanMechanic.SetCharacterTransform(characterTransform);
_wallRunningMechanic.Initialize(motor, _inputHandler);
}
// Текущий режим камеры для адаптации поведения
private CameraMode _currentCameraMode = CameraMode.FirstPerson;
// Инициализация контроллера
// private void Start()
// {
// motor.CharacterController = this; // Регистрация этого контроллера в движке
// _inputHandler.FirstPersonCameraRotation =
// motor.Transform.rotation; // Начальное вращение совпадает с персонажемс
// _wallLeanMechanic.SetCharacterTransform(characterTransform);
// }
// Обработка и преобразование входных данных от персонажа
public void SetInputs(ref CharacterInputs inputs)
{
// Обновляем таймер перезарядки слайда
_lastInputs = inputs;
// Обновляем таймеры механик
_slideMechanic.TickCooldown(Time.deltaTime);
_wallClimbMechanic.TickCooldown(Time.deltaTime);
// _wallClimbMechanic.TickCooldown(Time.deltaTime);
_wallRunningMechanic.Tick(Time.deltaTime);
// Если активен слайд - игнорируем весь остальной ввод
if (_slideMechanic.IsSliding)
{
// Во время слайда не обрабатываем движение, прыжки и спринт
_inputHandler.MoveInputVector = Vector3.zero;
_inputHandler.LookInputVector = Vector3.one;
_inputHandler.IsSprinting = false;
@@ -138,7 +114,6 @@ namespace Code.Gameplay.Character.Controller
return;
}
// Сохраняем текущий режим камеры
_currentCameraMode = inputs.CameraMode;
if (isAbilitiesBlocked)
@@ -161,42 +136,33 @@ namespace Code.Gameplay.Character.Controller
// Обработка остального ввода
_inputHandler.ProcessInputs(ref inputs, motor);
// Передаём запрос прыжка напрямую в систему движения по земле
// Передаём запрос прыжка
_groundMovement.RequestJump(inputs.JumpPressed);
}
// Обновление вращения персонажа на основе входных данных
public void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
{
if (_slideMechanic.IsSliding || _wallClimbMechanic.IsClimbingActive) return;
if (_slideMechanic.IsSliding || _wallRunningMechanic.IsWallRunning) return;
switch (_currentCameraMode)
{
// В FirstPerson режиме применяем вращение камеры напрямую к персонажу (только горизонталь)
case CameraMode.FirstPerson when _inputHandler.ShouldApplyCameraRotation:
// Немедленно применяем горизонтальное вращение камеры к персонажу
currentRotation = _inputHandler.FirstPersonCameraRotation;
break;
// В ThirdPerson режиме плавно поворачиваем персонаж в направлении движения
case CameraMode.ThirdPerson:
{
// Вращение применяется только если есть направление движения и разрешена резкость вращения
if (_inputHandler.LookInputVector.sqrMagnitude > 0 && _characterConfig.orientationSharpness > 0)
{
// Плавная интерполяция текущего направления к целевому с экспоненциальным сглаживанием
var smoothedLookInputDirection = Vector3.Slerp(
motor.CharacterForward,
_inputHandler.LookInputVector,
1f - Mathf.Exp(-_characterConfig.orientationSharpness * deltaTime)
).normalized;
// Установка нового вращения смотря в сглаженном направлении
currentRotation = Quaternion.LookRotation(smoothedLookInputDirection, motor.CharacterUp);
}
break;
}
// Заготовка на будущее (если понадобится)
case CameraMode.Static:
case CameraMode.Cinematic:
default:
@@ -204,38 +170,40 @@ namespace Code.Gameplay.Character.Controller
}
}
// Обновление скорости движения персонажа
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
// Если во время слайда запрошен прыжок — прерываем слайд
if (_slideMechanic.IsSliding && _groundMovement.JumpRequested)
{
_slideMechanic.EndSlide();
}
// Проверяем запрос слайда и запускаем его если можно
if (!_slideMechanic.IsSliding)
{
_slideMechanic.TryStartSlide(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation,
_inputHandler.LookInputVector);
}
// Если активен слайд - обрабатываем отдельно
else
{
_slideMechanic.HandleSlide(ref currentVelocity, deltaTime, motor);
return;
}
// === WALL RUNNING: обработка состояния ===
if (_wallRunningMechanic.IsWallRunning)
{
_wallRunningMechanic.HandleWallRun(ref currentVelocity, _lastInputs, deltaTime);
return;
}
// Если персонаж находится на земле
if (motor.GroundingStatus.IsStableOnGround)
{
_groundMovement.UpdateVelocity(ref currentVelocity, _inputHandler, motor, deltaTime);
}
// Если персонаж не находится на земле
// Если персонаж не на земле — стандартное воздушное движение
else
{
_airMovement.UpdateVelocity(ref currentVelocity, deltaTime);
// Отменяем прыжок (фикс проблемы с двойным прыжком после приземления)
_groundMovement.CancelJumpRequest();
}
}
@@ -246,60 +214,57 @@ namespace Code.Gameplay.Character.Controller
abilityBlockTimer = duration;
}
// Метод вызывается перед обновлением персонажа (можно использовать для подготовки)
public void BeforeCharacterUpdate(float deltaTime)
{
}
// Метод вызывается после обработки столкновения с землей
public void PostGroundingUpdate(float deltaTime)
{
// Если во время слайда персонаж оторвался от земли - заканчиваем слайд
if (_slideMechanic.IsSliding && !motor.GroundingStatus.IsStableOnGround)
{
_slideMechanic.EndSlide();
}
if (motor.GroundingStatus.IsStableOnGround)
{
_wallClimbMechanic.ResetWallClimbSession();
}
// if (motor.GroundingStatus.IsStableOnGround)
// {
// _wallClimbMechanic.ResetWallClimbSession();
// }
}
// Метод вызывается после обновления персонажа
public void AfterCharacterUpdate(float deltaTime)
{
_wallLeanMechanic.UpdateLean(motor, deltaTime);
}
// Проверка валидности коллайдера для обработки столкновений
public bool IsColliderValidForCollisions(Collider coll)
{
return true; // Все коллайдеры считаются валидными для столкновений
return true;
}
// Обработка столкновения с землей (вызывается при приземлении)
public void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
ref HitStabilityReport hitStabilityReport)
{
}
// Обработка столкновения при движении (вызывается при ударе о препятствие)
public void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
ref HitStabilityReport hitStabilityReport)
{
if (_wallClimbMechanic.TryClimbWall(motor, hitNormal))
// Попытка начать Wall Run при ударе о поверхность
if (_wallRunningMechanic.TryStartWallRun(hitNormal, hitPoint))
{
_wallLeanMechanic.OnWallContact(motor, hitNormal, motor.TransientPosition.y);
}
// if (_wallClimbMechanic.TryClimbWall(motor, hitNormal))
// _wallLeanMechanic.OnWallContact(motor, hitNormal, motor.TransientPosition.y);
}
// Обработка отчета о стабильности столкновения
public void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
Vector3 atCharacterPosition,
Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
{
}
// Обработка дискретных столкновений (для триггеров и специальных коллайдеров)
public void OnDiscreteCollisionDetected(Collider hitCollider)
{
}