Here's the Script:
using System.Collections;
using Cinemachine;
using Cinemachine.Utility;
using UnityEngine;
public class SnapToTarget : MonoBehaviour
{
public Transform m_target;
public CinemachineFreeLook m_freeLookCamera;
private bool m_rotating;
// Update is called once per frame
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
StartCoroutine(LookAtTarget(GetFreeLookYRange()));
}
}
/// <summary>
/// Call this to cancel the rotation, e.g. if the user rotates the FreeLook
/// </summary>
public void CancelRotation()
{
m_rotating = false;
}
/// <summary>
/// This is supposed to snap (or animate) the camera axis to look at the target
/// </summary>
private IEnumerator LookAtTarget(float yRange)
{
// This constant controls the speed of the lerp. 1 is fastest.
const float lerpAmount = 0.1f;
m_rotating = true;
while (m_rotating && m_target != null && m_freeLookCamera != null)
{
// How far away from center is the target?
var state = m_freeLookCamera.State;
var dir = m_target.position - state.CorrectedPosition;
var rot = state.CorrectedOrientation.GetCameraRotationToTarget(dir, state.ReferenceUp);
// Record the current settings
var current = new Vector2(m_freeLookCamera.m_YAxis.Value, m_freeLookCamera.m_XAxis.Value);
// First do the yaw
m_freeLookCamera.m_XAxis.Value = (current.y + rot.y * lerpAmount) % 360;
// Then do the pitch
m_freeLookCamera.m_YAxis.Value = Mathf.Clamp01(current.x + lerpAmount * rot.x / yRange);
// Are we there yet?
if (Mathf.Abs(m_freeLookCamera.m_YAxis.Value - current.x) < 0.01f
&& Mathf.Abs(m_freeLookCamera.m_XAxis.Value - current.y) < 0.01f)
{
m_rotating = false; // yes, close enough
}
yield return null;
}
}
/// <summary>
/// Deduces the Y axis angle range from the freeLook orbits
/// </summary>
private float GetFreeLookYRange()
{
if (m_freeLookCamera == null)
return 1;
var orbit = m_freeLookCamera.m_Orbits[2];
var d0 = new Vector3(0, orbit.m_Height, orbit.m_Radius);
orbit = m_freeLookCamera.m_Orbits[0];
var d1 = new Vector3(0, orbit.m_Height, orbit.m_Radius);
return Vector3.Angle(d0, d1);
}
}