Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- [RequireComponent(typeof(Camera))]
- public class GameCamera : MonoBehaviour
- {
- [Header("Runtime attributes")] [Tooltip("The point the camera is looking at")]
- public Transform cameraTarget;
- [Tooltip("The point the camera is going to")]
- public Transform cameraAnchor;
- [Tooltip("Setting this to true will widen the fov to 'wideFov' otherwise to 'defaultFov'")]
- public bool isWideMode;
- [Tooltip("Setting this to false won't smooth/lerp the fov")]
- public bool isRotationSmoothingEnabled = true;
- [Tooltip("Setting this to false won't smooth/lerp the position")]
- public bool isPositionSmoothingEnabled = true;
- [Tooltip("Setting this to false won't smooth/lerp the rotation")]
- public bool isFovSmoothingEnabled = true;
- [Tooltip("Setting this to false will prevent the camera from moving")]
- public bool lockPosition;
- [Tooltip("Setting this to false will prevent the camera from rotating")]
- public bool lockRotation;
- [Tooltip("Setting this to false will prevent the camera from changing fov")]
- public bool lockFov;
- // ReSharper disable once MemberCanBePrivate.Global
- // ReSharper disable once UnusedAutoPropertyAccessor.Global
- /// <summary>
- /// This value can be used to make your GUI react to camera movement.
- /// </summary>
- /// <example>
- /// myGuiTransform.position = myGuiTransform.initialPosition + GameCamera.CameraScreenSpaceMotion;
- /// </example>
- public Vector2 CameraScreenSpaceMotion { get; private set; }
- [Header("Configuration"), SerializeField]
- private UpdateMode currentUpdateMode;
- [Tooltip("The time it take for the spring to bring the camera to the target position"), SerializeField]
- public float positionSmoothing;
- [Tooltip("The time it take for the spring to bring the camera to the target rotation"), SerializeField]
- public float rotationSmoothing;
- [Tooltip("The time it take for the spring to bring the camera to the target FOV"), SerializeField]
- private float fovSmooth = 1f;
- [Tooltip("The amount of tilt to apply when you turn sideways"), SerializeField, Range(-1, 1)]
- private float cameraTilt;
- [Tooltip("The FOV to use by default"), SerializeField]
- private float defaultFov = 75;
- [Tooltip("The FOV to use when there is some action"), SerializeField]
- public float wideFov = 120;
- private Vector3 positionVelocity;
- private float xAngleVelocity;
- private float fovVelocity;
- private float yAngleVelocity;
- #region utils
- private Camera Camera => GetComponent<Camera>();
- private float DeltaTime => currentUpdateMode == UpdateMode.FixedUpdate ? Time.fixedDeltaTime : Time.deltaTime;
- private bool IsMissingTarget => cameraTarget == null || cameraAnchor == null;
- private Transform self;
- private void Awake()
- {
- self = transform; //Avoids regular calls to `this.transform` which is as slow as GetComponent<Transform>()
- }
- #endregion
- #region update_mode
- private enum UpdateMode
- {
- Update,
- LateUpdate,
- FixedUpdate
- }
- private void Update()
- {
- if (currentUpdateMode == UpdateMode.Update) CustomUpdate();
- }
- private void LateUpdate()
- {
- if (currentUpdateMode == UpdateMode.LateUpdate) CustomUpdate();
- }
- private void FixedUpdate()
- {
- if (currentUpdateMode == UpdateMode.FixedUpdate) CustomUpdate();
- }
- #endregion
- private void CustomUpdate()
- {
- if (IsMissingTarget) return;
- if (!lockPosition) UpdatePosition();
- if (!lockRotation) UpdateRotation();
- if (!lockFov) UpdateFov();
- }
- private void UpdateFov()
- {
- float target = isWideMode ? wideFov : defaultFov;
- if (isFovSmoothingEnabled) target = SmoothFov(target);
- Camera.fieldOfView = target;
- }
- private void UpdateRotation()
- {
- Vector3 target = Quaternion.LookRotation(cameraTarget.transform.position - transform.position).eulerAngles;
- if (isRotationSmoothingEnabled) target = SmoothRotation(target);
- Camera.transform.rotation = Quaternion.Euler(target);
- }
- private void UpdatePosition()
- {
- Vector3 previous = transform.position;
- Vector3 target = cameraAnchor.transform.position;
- if (isPositionSmoothingEnabled) target = SmoothPosition(target);
- self.position = target;
- CameraScreenSpaceMotion = target - previous;
- }
- #region smoothing
- private Vector3 SmoothRotation(Vector3 target)
- {
- Vector3 current = transform.rotation.eulerAngles;
- current.x = Mathf.SmoothDampAngle(current.x,
- target.x,
- ref xAngleVelocity,
- rotationSmoothing,
- float.MaxValue,
- DeltaTime
- );
- current.y = Mathf.SmoothDampAngle(current.y,
- target.y,
- ref yAngleVelocity,
- rotationSmoothing,
- float.MaxValue,
- DeltaTime
- );
- current.z = yAngleVelocity * -cameraTilt; //We never want to use z angle except for dynamic tilting
- return current;
- }
- private Vector3 SmoothPosition(Vector3 target)
- {
- return Vector3.SmoothDamp(
- self.position,
- target,
- ref positionVelocity,
- positionSmoothing,
- float.MaxValue,
- DeltaTime
- );
- }
- private float SmoothFov(float target)
- {
- float smoothTime = isWideMode ? fovSmooth : fovSmooth / 2f; //Fov comes back to normal twice as fast
- return Mathf.SmoothDamp(Camera.fieldOfView, target, ref fovVelocity, smoothTime, float.MaxValue, DeltaTime);
- }
- #endregion
- #region gizmos
- private void OnDrawGizmos()
- {
- DrawGizmos(.25f, .1f);
- }
- private void OnDrawGizmosSelected()
- {
- DrawGizmos(.75f, .2f);
- }
- private void DrawGizmos(float alpha, float size)
- {
- if (cameraTarget != null)
- {
- Gizmos.color = new Color(0f, 1f, .5f, alpha);
- Gizmos.DrawSphere(cameraTarget.position, size);
- Gizmos.DrawLine(transform.position, cameraTarget.position);
- }
- if (cameraAnchor != null)
- {
- Gizmos.color = new Color(0f, .5f, 1f, alpha);
- Gizmos.DrawSphere(cameraAnchor.position, size);
- Gizmos.DrawLine(transform.position, cameraAnchor.position);
- }
- Gizmos.color = new Color(.5f, 1f, .5f, alpha);
- Gizmos.DrawSphere(transform.position, size);
- }
- #endregion
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement