init
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Player.Input;
|
||||
|
||||
namespace VOID.Generic.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Manager with full control of camera with movement by player.
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-1)]
|
||||
public class CameraManager : MonoBehaviour
|
||||
{
|
||||
public static CameraManager current {get; private set;}
|
||||
|
||||
// Camera Movement Settings
|
||||
[Title("Camera Horizontal Movement")]
|
||||
[SerializeField, MinValue(1f), MaxValue(10f), SuffixLabel("m/s")]
|
||||
private float moveSpeed = 5f;
|
||||
[SerializeField, MinValue(1f), MaxValue(5f)]
|
||||
private float moveSpeedFastMultiplier = 2.5f;
|
||||
|
||||
// Camera's target elevating
|
||||
[Title("Camera Vertical Movement")]
|
||||
[SerializeField, MinValue(1f), MaxValue(20f), SuffixLabel("m/s")]
|
||||
private float elevateSpeed = 1f;
|
||||
|
||||
// Camera Rotate and Tilt Settings
|
||||
[Title("Camera Rotate and Tilt")]
|
||||
[SerializeField, MinValue(0.01f), MaxValue(1f)]
|
||||
private float rotateSensitivity = 0.1f;
|
||||
[SerializeField, MinValue(0.01f), MaxValue(1f)]
|
||||
private float tiltSensitivity = 0.06f;
|
||||
[SerializeField, MinMaxSlider(10f, 90f, true)]
|
||||
private Vector2 tiltLimit = new(20f, 85f);
|
||||
|
||||
// Camera Zoom Settings
|
||||
[Title("Camera Zoom")]
|
||||
[SerializeField, MinValue(0.05f), MaxValue(1f)]
|
||||
private float zoomSensitivity = 0.3f;
|
||||
[SerializeField, MinMaxSlider(1f, 30f, true)]
|
||||
private Vector2 zoomLimit = new(2f, 15f);
|
||||
[SerializeField]
|
||||
private float zoomCurrent = 8f;
|
||||
|
||||
// Camera Offset
|
||||
[Title("Camera Offset")]
|
||||
[SerializeField, MinValue(0f), MaxValue(3f)]
|
||||
private float targetVerticalOffset = 1.0f;
|
||||
[SerializeField]
|
||||
private Vector3 cameraOffset = new(0f, 0f, -1f);
|
||||
|
||||
// Camera and Target
|
||||
private Camera _camera;
|
||||
private GameObject _target;
|
||||
|
||||
// Stick properties
|
||||
[Title("Sticking to transform")]
|
||||
public Transform stickTo;
|
||||
|
||||
// Aditional Components
|
||||
private CameraInputManager _cameraInputManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
current = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_cameraInputManager = CameraInputManager.current;
|
||||
|
||||
_camera = Camera.main;
|
||||
_target = CameraTarget.InstantiateNew().gameObject;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
MoveHorizontally();
|
||||
MoveVertically();
|
||||
RotateAndTilt();
|
||||
Zoom();
|
||||
Offset();
|
||||
CameraLookAtTarget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves camera's target to given position.
|
||||
/// </summary>
|
||||
public void MoveTo(Vector3 position)
|
||||
{
|
||||
_target.transform.position = position;
|
||||
stickTo = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moving camera's target horizontally.
|
||||
/// </summary>
|
||||
private void MoveHorizontally()
|
||||
{
|
||||
// No camera movement from player, but it can be sticked to something
|
||||
if (!_cameraInputManager.isMoving) {
|
||||
if (stickTo) _target.transform.position = stickTo.position + new Vector3(0f, 1.5f, 0f);
|
||||
return;
|
||||
}
|
||||
|
||||
// Player moved camera - unstick camera
|
||||
stickTo = null;
|
||||
|
||||
// Calculate camera's target next relative position
|
||||
var moveVector = _cameraInputManager.movementDelta * (moveSpeed * Time.deltaTime);
|
||||
if (_cameraInputManager.isMovingFaster) moveVector *= moveSpeedFastMultiplier;
|
||||
|
||||
var position = _target.transform.TransformDirection(moveVector.x, 0, moveVector.y);
|
||||
_target.transform.position += position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moving camera's target vertically.
|
||||
/// </summary>
|
||||
private void MoveVertically()
|
||||
{
|
||||
// IMPORTANT - target's pos already include offset!
|
||||
var targetPos = _target.transform.position;
|
||||
|
||||
// Find point where camera's target can stick to
|
||||
Physics.Raycast(
|
||||
new Ray(targetPos + Vector3.up*50f, Vector3.down),
|
||||
out var rayCastHit,
|
||||
100f,
|
||||
LayerManager.Static);
|
||||
|
||||
// Nothing - seems like camera floating and there is nothing above or below
|
||||
if (!rayCastHit.collider) return;
|
||||
|
||||
// IMPORTANT - target include offset by default, but not raycast - we need add offset to raycast point!
|
||||
var rayCastPos = rayCastHit.point + new Vector3(0, targetVerticalOffset, 0);
|
||||
|
||||
// If distance is positive we go UP, otherwise we go DOWN
|
||||
var distance = rayCastPos.y - targetPos.y;
|
||||
|
||||
// Move camera's target towards new position, if really close then move remaining distance to prevent jiggling
|
||||
var speed = Mathf.Sign(distance) * Mathf.Min(Mathf.Abs(distance), elevateSpeed * Time.fixedDeltaTime);
|
||||
_target.transform.position += new Vector3(0f, speed, 0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotating and tilting camera.<br/>
|
||||
/// Rotating camera's target.
|
||||
/// </summary>
|
||||
private void RotateAndTilt()
|
||||
{
|
||||
if (_cameraInputManager.isRotatingAndTilting == false) return;
|
||||
|
||||
var delta = _cameraInputManager.rotateAndTiltDelta;
|
||||
var tiltDelta = delta.y * tiltSensitivity * -1;
|
||||
var rotateDelta = delta.x * rotateSensitivity;
|
||||
|
||||
var previousEuler = _camera.transform.rotation.eulerAngles;
|
||||
var nextEuler = previousEuler + new Vector3(tiltDelta, rotateDelta, 0);
|
||||
|
||||
if (nextEuler.x < tiltLimit.x) nextEuler.x = tiltLimit.x;
|
||||
if (nextEuler.x > tiltLimit.y) nextEuler.x = tiltLimit.y;
|
||||
|
||||
_camera.transform.rotation = Quaternion.Euler(nextEuler);
|
||||
_target.transform.rotation = Quaternion.Euler(0f, nextEuler.y, 0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updating camera's zoom.
|
||||
/// </summary>
|
||||
private void Zoom()
|
||||
{
|
||||
if (_cameraInputManager.isZooming == false) return;
|
||||
|
||||
zoomCurrent -= _cameraInputManager.zoomDelta * zoomSensitivity;
|
||||
|
||||
if (zoomCurrent > zoomLimit.y) zoomCurrent = zoomLimit.y;
|
||||
if (zoomCurrent < zoomLimit.x) zoomCurrent = zoomLimit.x;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updating camera's offset from target.
|
||||
/// </summary>
|
||||
private void Offset()
|
||||
{
|
||||
var offset = _camera.transform.TransformDirection(Vector3.back * zoomCurrent + cameraOffset);
|
||||
_camera.transform.position = _target.transform.position + offset;
|
||||
}
|
||||
|
||||
private void CameraLookAtTarget()
|
||||
{
|
||||
_camera.transform.LookAt(_target.transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user