summaryrefslogtreecommitdiff
path: root/Assets/Scripts/Camera/CameraFollow.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/Scripts/Camera/CameraFollow.cs')
-rw-r--r--Assets/Scripts/Camera/CameraFollow.cs121
1 files changed, 121 insertions, 0 deletions
diff --git a/Assets/Scripts/Camera/CameraFollow.cs b/Assets/Scripts/Camera/CameraFollow.cs
new file mode 100644
index 0000000..47b96f4
--- /dev/null
+++ b/Assets/Scripts/Camera/CameraFollow.cs
@@ -0,0 +1,121 @@
+using System;
+using JetBrains.Annotations;
+using UnityEngine;
+
+namespace Camera
+{
+ public class CameraFollow : MonoBehaviour
+ {
+ [CanBeNull] public static CameraFollow Current;
+ private Transform _followTarget;
+
+ private float _defaultYaw;
+ private bool _enableMove;
+ private float _height;
+
+ [CanBeNull]
+ public Transform followTarget
+ {
+ get => _followTarget;
+ set {
+ if (_followTarget == value) return;
+
+ _followTarget = value;
+
+ if (_followTarget != null)
+ OnFollowTargetChanged(value);
+ else
+ OnFollowTargetLost();
+ }
+ }
+
+ private void Awake()
+ {
+ _defaultYaw = rotationYaw.eulerAngles.y;
+
+ if (Current != null)
+ Debug.LogWarning("Duplicate CameraFollow Found!");
+ Current = this;
+ followTarget = defaultFollowTarget;
+ }
+
+ [Header("Parameters")]
+ [SerializeField] private bool enableYaw;
+ [SerializeField] private Transform defaultFollowTarget;
+ [SerializeField] [Range(0.015f, 1f)] private float yawRotationLerp;
+ [SerializeField] [Range(0.015f, 1f)] private float positionLerp;
+ [SerializeField] [Range(0.015f, 1f)] private float heightLerp;
+ [SerializeField] private LayerMask heightCheckLayerMask;
+
+ [Header("Bindings")]
+ [SerializeField] private Transform rotationYaw;
+ [SerializeField] private Transform rotationPitch;
+ [SerializeField] private Transform positionCamera;
+ [SerializeField] private Transform positionHeight;
+
+ private void OnFollowTargetChanged([CanBeNull] Transform target)
+ {
+ Debug.Log($"Follow target: {target?.name}");
+ _enableMove = target != null;
+ }
+
+ private void OnFollowTargetLost()
+ {
+ Debug.Log("Follow target lost");
+ _enableMove = false;
+ }
+
+ private void FixedUpdate()
+ {
+ FixedUpdateHeight();
+
+ if (_enableMove)
+ {
+ try
+ {
+ FixedUpdateMoveCamera();
+ }
+ catch (NullReferenceException)
+ {
+ OnFollowTargetLost();
+ }
+ }
+ }
+
+ private void FixedUpdateMoveCamera()
+ {
+ var transformYaw = _followTarget.rotation.eulerAngles.y;
+ var transformPosition = _followTarget.position;
+
+ var targetYaw = transformYaw;
+ var targetYawRotation = Quaternion.Euler(0, enableYaw ? targetYaw : _defaultYaw, 0);
+ var targetPosition = new Vector3(transformPosition.x, 0, transformPosition.z);
+
+ transform.position = Vector3.Lerp(transform.position, targetPosition, positionLerp);
+ rotationYaw.rotation = Quaternion.Lerp(rotationYaw.rotation, targetYawRotation, yawRotationLerp);
+ positionHeight.position = new Vector3(
+ transformPosition.x,
+ Mathf.Lerp(positionHeight.position.y, _height, heightLerp),
+ transformPosition.z
+ );
+ }
+
+ private void FixedUpdateHeight()
+ {
+ var transformPosition = transform.position;
+ var start = transformPosition + Vector3.up * 100;
+ var end = transformPosition + Vector3.down * 100;
+ Physics.Linecast(start, end, out RaycastHit hit, heightCheckLayerMask);
+ if (hit.collider == null)
+ _height = transformPosition.y;
+ else
+ _height = hit.point.y;
+ }
+
+ private void OnDestroy()
+ {
+ if (Current == this)
+ Current = null;
+ }
+ }
+}