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