Добавлено базовое перемещение, тестовый материал
This commit is contained in:
1 parent
86c9c126a6
commit
8981457f2d
35 files changed
+1052
-6
No files matched your search
@@ -0,0 +1,157 @@
|
||||
using KinematicCharacterController;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Player
|
||||
{
|
||||
/*
|
||||
* Скрипт, отвечающий за передвижения игрока
|
||||
* Реализует физическое движение персонажа с использованием Kinematic Character Controller
|
||||
* Обрабатывает ввод пользователя, применяет движение и вращение с учетом поверхности
|
||||
*
|
||||
* Источник: Tvtig, https://www.youtube.com/watch?v=9ibpY64wBYM
|
||||
*/
|
||||
|
||||
// Структура для хранения входных данных от игрока
|
||||
public struct PlayerInputs
|
||||
{
|
||||
public float MoveAxisForward; // Ввод движения вперед/назад (W/S или Up/Down)
|
||||
public float MoveAxisRight; // Ввод движения влево/вправо (A/D или Left/Right)
|
||||
public Quaternion CameraRotation; // Текущее вращение камеры для определения направления движения
|
||||
}
|
||||
|
||||
public class CharacterController : MonoBehaviour, ICharacterController
|
||||
{
|
||||
[SerializeField]
|
||||
private KinematicCharacterMotor motor; // Движок физического перемещения персонажа
|
||||
|
||||
[SerializeField]
|
||||
private float
|
||||
maxStableMoveSpeed = 10f, // Максимальная скорость движения по устойчивой поверхности
|
||||
stableMovementSharpness = 15f, // Резкость изменения скорости движения (чем выше - тем резче)
|
||||
orientationSharpness = 10f; // Резкость изменения вращения персонажа (чем выше - тем резче)
|
||||
|
||||
// Векторы движения и направления взгляда
|
||||
private Vector3 _moveInputVector, _lookInputVector;
|
||||
|
||||
// Инициализация контроллера
|
||||
private void Start()
|
||||
{
|
||||
motor.CharacterController = this; // Регистрация этого контроллера в движке
|
||||
}
|
||||
|
||||
// Обработка и преобразование входных данных от игрока
|
||||
public void SetInputs(ref PlayerInputs inputs)
|
||||
{
|
||||
// Нормализация вектора движения и ограничение его величины до 1
|
||||
Vector3 moveInputVector =
|
||||
Vector3.ClampMagnitude(new Vector3(inputs.MoveAxisRight, 0, inputs.MoveAxisForward), 1f);
|
||||
|
||||
// Получение направления камеры в горизонтальной плоскости (игнорируя наклон)
|
||||
Vector3 cameraPlanarDirection =
|
||||
Vector3.ProjectOnPlane(inputs.CameraRotation * Vector3.forward, motor.CharacterUp).normalized;
|
||||
|
||||
// Резервный расчет направления, если основное направление параллельно вертикали
|
||||
if (cameraPlanarDirection.sqrMagnitude == 0f)
|
||||
{
|
||||
cameraPlanarDirection = Vector3.ProjectOnPlane(inputs.CameraRotation * Vector3.up, motor.CharacterUp);
|
||||
}
|
||||
|
||||
// Создание вращения на основе направления камеры
|
||||
Quaternion cameraPlanarRotation = Quaternion.LookRotation(cameraPlanarDirection, motor.CharacterUp);
|
||||
|
||||
// Преобразование локального ввода в мировые координаты относительно камеры
|
||||
_moveInputVector = cameraPlanarRotation * moveInputVector;
|
||||
|
||||
// Направление взгляда совпадает с направлением движения (нормализованное)
|
||||
_lookInputVector = _moveInputVector.normalized;
|
||||
}
|
||||
|
||||
// Обновление вращения персонажа на основе входных данных
|
||||
public void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
// Вращение применяется только если есть направление движения и разрешена резкость вращения
|
||||
if (_lookInputVector.sqrMagnitude > 0 && orientationSharpness > 0)
|
||||
{
|
||||
// Плавная интерполяция текущего направления к целевому с экспоненциальным сглаживанием
|
||||
Vector3 smoothedLookInputDirection = Vector3.Slerp(
|
||||
motor.CharacterForward,
|
||||
_lookInputVector,
|
||||
1f - Mathf.Exp(-orientationSharpness * deltaTime)
|
||||
).normalized;
|
||||
|
||||
// Установка нового вращения смотря в сглаженном направлении
|
||||
currentRotation = Quaternion.LookRotation(smoothedLookInputDirection, motor.CharacterUp);
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление скорости движения персонажа
|
||||
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
// Сохранение текущей величины скорости
|
||||
float currentVelocityMagnitude = currentVelocity.magnitude;
|
||||
|
||||
// Получение нормали поверхности для корректного движения по наклонным плоскостям
|
||||
Vector3 effectiveGroundNormal = motor.GroundingStatus.GroundNormal;
|
||||
|
||||
// Переориентация текущей скорости вдоль поверхности
|
||||
currentVelocity = motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) * currentVelocityMagnitude;
|
||||
|
||||
// Переориентация входного вектора движения вдоль поверхности
|
||||
Vector3 inputRight = Vector3.Cross(_moveInputVector, motor.CharacterUp);
|
||||
Vector3 reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized * _moveInputVector.magnitude;
|
||||
|
||||
// Расчет целевой скорости движения с учетом ограничения максимальной скорости
|
||||
Vector3 targetMovementVelocity = reorientedInput * maxStableMoveSpeed;
|
||||
|
||||
// Плавная интерполяция текущей скорости к целевой с экспоненциальным сглаживанием
|
||||
currentVelocity = Vector3.Lerp(
|
||||
currentVelocity,
|
||||
targetMovementVelocity,
|
||||
1f - Mathf.Exp(-stableMovementSharpness * deltaTime)
|
||||
);
|
||||
}
|
||||
|
||||
// Метод вызывается перед обновлением персонажа (можно использовать для подготовки)
|
||||
public void BeforeCharacterUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
// Метод вызывается после обработки столкновения с землей
|
||||
public void PostGroundingUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
// Метод вызывается после обновления персонажа (можно использовать для пост-обработки)
|
||||
public void AfterCharacterUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
// Проверка валидности коллайдера для обработки столкновений
|
||||
public bool IsColliderValidForCollisions(Collider coll)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
// Обработка отчета о стабильности столкновения
|
||||
public void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition,
|
||||
Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
// Обработка дискретных столкновений (для триггеров и специальных коллайдеров)
|
||||
public void OnDiscreteCollisionDetected(Collider hitCollider)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6f74123648343c498c883d02909b499
|
||||
timeCreated: 1760641740
|
||||
@@ -2,12 +2,15 @@ using Code.Gameplay.Player;
|
||||
using Code.Input;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using CharacterController = Code.Gameplay.Player.CharacterController;
|
||||
|
||||
public class Player : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private PlayerCamera playerCamera;
|
||||
[SerializeField]
|
||||
private CharacterController characterController;
|
||||
[SerializeField]
|
||||
private Transform cameraFollowPoint;
|
||||
[Inject] private IInputService _inputService;
|
||||
|
||||
@@ -27,6 +30,24 @@ public class Player : MonoBehaviour
|
||||
new Vector3(lookInput.x, lookInput.y, 0));
|
||||
}
|
||||
|
||||
private void HandleCharacterInput()
|
||||
{
|
||||
PlayerInputs inputs = new PlayerInputs();
|
||||
|
||||
Vector2 moveInput = _inputService.MoveInput;
|
||||
inputs.MoveAxisForward = moveInput.y;
|
||||
inputs.MoveAxisRight = moveInput.x;
|
||||
|
||||
inputs.CameraRotation = playerCamera.transform.rotation;
|
||||
|
||||
characterController.SetInputs(ref inputs);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
HandleCharacterInput();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
HandleCameraInput();
|
||||
|
||||
Reference in new issue
Block a user