71 lines
2.5 KiB
C#
71 lines
2.5 KiB
C#
using RaceFields.Vehicles;
|
|
using UnityEngine;
|
|
|
|
namespace RaceFields.CameraSystem
|
|
{
|
|
[RequireComponent(typeof(Camera))]
|
|
public sealed class RearViewMirrorCamera : MonoBehaviour
|
|
{
|
|
[SerializeField] private Transform target;
|
|
[SerializeField] private bool autoFindTarget = true;
|
|
[SerializeField] private float targetSearchInterval = 0.35f;
|
|
[SerializeField] private Vector3 localOffset = new Vector3(0f, 2.1f, 0.6f);
|
|
[SerializeField] private float lookUpBias = 0.08f;
|
|
[SerializeField] private float positionLerp = 18f;
|
|
[SerializeField] private float rotationLerp = 18f;
|
|
|
|
private Camera mirrorCamera;
|
|
private float nextTargetSearchTime;
|
|
|
|
private void Awake()
|
|
{
|
|
mirrorCamera = GetComponent<Camera>();
|
|
mirrorCamera.enabled = true;
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
ResolveTarget();
|
|
if (target == null)
|
|
return;
|
|
|
|
Vector3 desiredPosition = target.TransformPoint(localOffset);
|
|
Vector3 lookDirection = -target.forward + Vector3.up * lookUpBias;
|
|
Quaternion desiredRotation = Quaternion.LookRotation(lookDirection.normalized, Vector3.up);
|
|
|
|
float positionStep = 1f - Mathf.Exp(-positionLerp * Time.deltaTime);
|
|
float rotationStep = 1f - Mathf.Exp(-rotationLerp * Time.deltaTime);
|
|
transform.position = Vector3.Lerp(transform.position, desiredPosition, positionStep);
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, rotationStep);
|
|
}
|
|
|
|
public void SetTarget(Transform newTarget, bool snap)
|
|
{
|
|
target = newTarget;
|
|
if (snap && target != null)
|
|
SnapToTarget();
|
|
}
|
|
|
|
private void SnapToTarget()
|
|
{
|
|
transform.position = target.TransformPoint(localOffset);
|
|
Vector3 lookDirection = -target.forward + Vector3.up * lookUpBias;
|
|
transform.rotation = Quaternion.LookRotation(lookDirection.normalized, Vector3.up);
|
|
}
|
|
|
|
private void ResolveTarget()
|
|
{
|
|
if (target != null || !autoFindTarget)
|
|
return;
|
|
|
|
if (Time.unscaledTime < nextTargetSearchTime)
|
|
return;
|
|
|
|
nextTargetSearchTime = Time.unscaledTime + targetSearchInterval;
|
|
ArcadeBuggyController controller = Object.FindFirstObjectByType<ArcadeBuggyController>();
|
|
if (controller != null)
|
|
SetTarget(controller.transform, true);
|
|
}
|
|
}
|
|
}
|