153 lines
4.4 KiB
C#
153 lines
4.4 KiB
C#
using System;
|
|
using Common.Abstracts;
|
|
using Common.Events;
|
|
using MessagePipe;
|
|
using Unity.Cinemachine;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using VContainer;
|
|
|
|
namespace Player
|
|
{
|
|
public class PlayerController : AbstractMonoListener
|
|
{
|
|
[Inject] private ISubscriber<ScreenResizeEvent> _screenResizeSubscriber;
|
|
|
|
private InputAction _moveAction;
|
|
|
|
private InputAction _sprintAction;
|
|
|
|
private InputAction _scrollAction;
|
|
|
|
private InputAction _lookAction;
|
|
|
|
private InputAction _interactAction;
|
|
|
|
private Vector3 _position;
|
|
|
|
private Vector2 _targetMovement;
|
|
|
|
private Vector2 _currentMovement;
|
|
|
|
private bool _isSprinting;
|
|
|
|
private Transform _follow;
|
|
|
|
private float _rotationAngle;
|
|
|
|
private float _rotationVelocity;
|
|
|
|
private Quaternion _targetRotation;
|
|
|
|
private Camera _camera;
|
|
|
|
private CinemachineCamera _cinemachineCamera;
|
|
|
|
private Vector3 _centerScreenPoint;
|
|
|
|
private RaycastHit[] _landHit;
|
|
|
|
private Ray _landRay;
|
|
|
|
[SerializeField] private Vector2 heightLimits = new Vector2(0.5f, 40f);
|
|
|
|
[SerializeField] private float currentHeight = 15f;
|
|
|
|
[SerializeField] private float moveSpeed = 5f;
|
|
|
|
[SerializeField] private float inputSmooth = 10f;
|
|
|
|
[SerializeField] private Vector3 landHitDisplace = new Vector3(0, 1f, 0);
|
|
|
|
[SerializeField] private float angle = 45f;
|
|
|
|
private void Start()
|
|
{
|
|
InputSystem.actions.actionMaps[0].Enable();
|
|
|
|
_moveAction = InputSystem.actions.FindAction("Move");
|
|
_moveAction.performed += SetMovement;
|
|
_moveAction.canceled += SetMovement;
|
|
|
|
_sprintAction = InputSystem.actions.FindAction("Sprint");
|
|
_sprintAction.performed += SetSprint;
|
|
_sprintAction.canceled += SetSprint;
|
|
|
|
_position = transform.position;
|
|
|
|
_camera = Camera.main;
|
|
_landHit = new RaycastHit[5];
|
|
_landRay = new Ray(_position, Vector3.down);
|
|
|
|
_follow = new GameObject("Follow").transform;
|
|
_follow.eulerAngles = new Vector3(angle, 0);
|
|
|
|
_cinemachineCamera = GetComponent<CinemachineCamera>();
|
|
_cinemachineCamera.Follow = _follow;
|
|
|
|
CreateSubscriber(_screenResizeSubscriber, OnScreenResize);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
Move();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
_moveAction.performed -= SetMovement;
|
|
_moveAction.canceled -= SetMovement;
|
|
|
|
_sprintAction.performed -= SetSprint;
|
|
_sprintAction.canceled -= SetSprint;
|
|
}
|
|
|
|
private void SetMovement(InputAction.CallbackContext callbackContext)
|
|
{
|
|
_targetMovement = callbackContext.ReadValue<Vector2>();
|
|
_currentMovement = Vector2.MoveTowards(_currentMovement, _targetMovement,
|
|
inputSmooth * Time.deltaTime);
|
|
}
|
|
|
|
private void SetSprint(InputAction.CallbackContext callbackContext)
|
|
{
|
|
_isSprinting = callbackContext.ReadValueAsButton();
|
|
}
|
|
|
|
private void Move()
|
|
{
|
|
_landRay.origin = _position + landHitDisplace;
|
|
var cnt = Physics.RaycastNonAlloc(_landRay, _landHit);
|
|
|
|
if (cnt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var pos = _landHit[0].point;
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
if (_landHit[0].point.y > pos.y)
|
|
{
|
|
pos = _landHit[0].point;
|
|
}
|
|
}
|
|
|
|
Vector3 forward = transform.forward;
|
|
forward = new Vector3(forward.x, 0, forward.z).normalized;
|
|
Vector3 right = Quaternion.Euler(0, 90, 0) * forward;
|
|
Vector3 newPosition = transform.position +
|
|
(_currentMovement.y * forward + _currentMovement.x * right) * moveSpeed;
|
|
|
|
_position = Vector3.Lerp(_position, newPosition, Time.deltaTime);
|
|
_position.y = Mathf.Lerp(_position.y, pos.y + currentHeight, Time.deltaTime);
|
|
|
|
_follow.position = _position;
|
|
}
|
|
|
|
private void OnScreenResize(ScreenResizeEvent screenResizeEvent)
|
|
{
|
|
_centerScreenPoint = new Vector3(screenResizeEvent.width / 2, screenResizeEvent.height / 2);
|
|
}
|
|
}
|
|
} |