AsteroidGame/Assets/Scripts/CameraController.cs

214 lines
6.8 KiB
C#

using InputSystem;
using UnityEngine;
using UnityEngine.InputSystem;
namespace AsteroidGame
{
public class CameraController : MonoBehaviour
{
private CameraControllActions _cameraActions;
private InputAction _movement;
private Transform _cameraTransform;
private Camera _cameraReference;
// Horizontal Movement
[SerializeField]
private float _maxSpeed = 5f;
private float _speed;
[SerializeField]
private float _acceleration = 10f;
[SerializeField]
private float _damping = 15f;
//Vertial Motion - Zooming
[SerializeField]
private float _stepSize = 2f;
[SerializeField]
private float _zoomDampening = 7.5f;
[SerializeField]
private float _minHeight = 5f;
[SerializeField]
private float _maxHeight = 50f;
[SerializeField]
private float _zoomSpeed = 2f;
//Rotation
[SerializeField]
private float _maxRotationSpeed = 1f;
//Screen Edge Motion
[SerializeField]
[Range(0f, 0.1f)]
private float _edgeTolerance = 0.05f;
[SerializeField]
private bool _useScreenEdge = false;
private Vector3 _targetPosition;
private float _zoomHeight;
private Vector3 _horizontalVelocity;
private Vector3 _lastPosition;
private Plane _cameraPlane;
Vector3 _startDrag;
private void Awake()
{
_cameraActions = new CameraControllActions();
_cameraReference = this.GetComponentInChildren<Camera>();
_cameraTransform = _cameraReference.transform;
}
private void OnEnable()
{
_cameraPlane = new Plane(Vector3.up, Vector3.zero);
_zoomHeight = _cameraTransform.localPosition.y;
_cameraTransform.LookAt(this.transform);
_lastPosition = this.transform.position;
_movement = _cameraActions.Camera.Movement;
_cameraActions.Camera.RotateCamera.performed += RotateCamera;
_cameraActions.Camera.ZoomCamera.performed += ZoomCamera;
_cameraActions.Camera.Enable();
}
private void OnDisable()
{
_cameraActions.Camera.RotateCamera.performed -= RotateCamera;
_cameraActions.Camera.ZoomCamera.performed -= ZoomCamera;
_cameraActions.Disable();
}
private void Update()
{
GetKeyboardMovement();
if (_useScreenEdge)
{
CheckMouseAtScreenEdge();
}
DragCamera();
UpdateVelocity();
UpdateCameraPosition();
UpdateBasePosition();
}
private void UpdateVelocity()
{
_horizontalVelocity = (this.transform.position - _lastPosition) / Time.deltaTime;
_horizontalVelocity.y = 0;
_lastPosition = this.transform.position;
}
private void GetKeyboardMovement()
{
Vector3 inputValue = _movement.ReadValue<Vector2>().x * GetCameraRight()
+ _movement.ReadValue<Vector2>().y * GetCameraForward();
inputValue = inputValue.normalized;
if (inputValue.sqrMagnitude > 0.1f)
{
_targetPosition += inputValue;
}
}
private Vector3 GetCameraRight()
{
Vector3 right = _cameraTransform.right;
right.y = 0;
return right;
}
private Vector3 GetCameraForward()
{
Vector3 forward = _cameraTransform.forward;
forward.y = 0;
return forward;
}
private void UpdateBasePosition()
{
if (_targetPosition.sqrMagnitude > 0.1f)
{
_speed = Mathf.Lerp(_speed, _maxSpeed, Time.deltaTime * _acceleration);
transform.position += _speed * Time.deltaTime * _targetPosition;
}
else
{
_horizontalVelocity = Vector3.Lerp(_horizontalVelocity, Vector3.zero, Time.deltaTime * _damping);
transform.position += _horizontalVelocity * Time.deltaTime;
}
_targetPosition = Vector3.zero;
}
private void RotateCamera(InputAction.CallbackContext inputValue)
{
if (!Mouse.current.middleButton.isPressed) { return; }
float value = inputValue.ReadValue<Vector2>().x;
transform.rotation = Quaternion.Euler(0f, value * _maxRotationSpeed + transform.rotation.eulerAngles.y, 0f);
}
private void ZoomCamera(InputAction.CallbackContext inputValue)
{
float value = -inputValue.ReadValue<Vector2>().y / 100f;
if (Mathf.Abs(value) > 0.1f)
{
_zoomHeight = _cameraTransform.localPosition.y + value * _stepSize;
if (_zoomHeight < _minHeight)
_zoomHeight = _minHeight;
else if (_zoomHeight > _maxHeight)
_zoomHeight = _maxHeight;
}
}
private void UpdateCameraPosition()
{
Vector3 zoomTarget = new Vector3(_cameraTransform.localPosition.x, _zoomHeight, _cameraTransform.localPosition.z);
zoomTarget -= _zoomSpeed * (_zoomHeight - _cameraTransform.localPosition.y) * Vector3.forward;
_cameraTransform.localPosition = Vector3.Lerp(_cameraTransform.localPosition, zoomTarget, Time.deltaTime * _zoomDampening);
_cameraTransform.LookAt(this.transform);
}
private void CheckMouseAtScreenEdge()
{
Vector2 mousePosition = Mouse.current.position.ReadValue();
Vector3 moveDirection = Vector3.zero;
if (mousePosition.x < _edgeTolerance * Screen.width)
moveDirection += -GetCameraRight();
else if (mousePosition.x > (1f - _edgeTolerance) * Screen.width)
moveDirection += GetCameraRight();
if (mousePosition.y < _edgeTolerance * Screen.height)
moveDirection += -GetCameraForward();
else if (mousePosition.y > (1f - _edgeTolerance) * Screen.height)
moveDirection += GetCameraForward();
_targetPosition += moveDirection;
}
private void DragCamera()
{
if (!Mouse.current.rightButton.isPressed) { return; }
Ray ray = _cameraReference.ScreenPointToRay(Mouse.current.position.ReadValue());
if (_cameraPlane.Raycast(ray,out float distance))
{
if (Mouse.current.rightButton.wasPressedThisFrame)
_startDrag = ray.GetPoint(distance);
else
_targetPosition += _startDrag - ray.GetPoint(distance);
}
}
}
}