cultivation/Assets/Scripts/Player/PlayerController.cs
2025-10-26 23:46:28 +03:00

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);
}
}
}