using System; using UnityEngine; namespace Unity.Cinemachine { /// /// This is a CinemachineComponent in the Aim section of the component pipeline. /// Its job is to aim the camera hard at the LookAt target. /// [AddComponentMenu("Cinemachine/Procedural/Rotation Control/Cinemachine Hard Look At")] [SaveDuringPlay] [DisallowMultipleComponent] [CameraPipeline(CinemachineCore.Stage.Aim)] [RequiredTarget(RequiredTargetAttribute.RequiredTargets.LookAt)] [HelpURL(Documentation.BaseURL + "manual/CinemachineHardLookAt.html")] public class CinemachineHardLookAt : CinemachineComponentBase { /// True if component is enabled and has a LookAt defined public override bool IsValid { get => enabled && LookAtTarget != null; } /// Get the Cinemachine Pipeline stage that this component implements. /// Always returns the Aim stage public override CinemachineCore.Stage Stage { get => CinemachineCore.Stage.Aim; } /// /// True if this component tries to make the camera look at the Tracking Target. /// Used by inspector to warn the user of potential improper setup. /// internal override bool CameraLooksAtTarget { get => true; } /// /// Offset from the LookAt target's origin, in target's local space. The camera will look at this point. /// [Tooltip("Offset from the LookAt target's origin, in target's local space. The camera will look at this point.")] public Vector3 LookAtOffset = Vector3.zero; void Reset() { LookAtOffset = Vector3.zero; } /// Applies the composer rules and orients the camera accordingly /// The current camera state /// Used for calculating damping. If less than /// zero, then target will snap to the center of the dead zone. public override void MutateCameraState(ref CameraState curState, float deltaTime) { if (IsValid && curState.HasLookAt()) { var offset = LookAtTargetRotation * LookAtOffset; Vector3 dir = ((curState.ReferenceLookAt + offset) - curState.GetCorrectedPosition()); if (dir.magnitude > Epsilon) { if (Vector3.Cross(dir.normalized, curState.ReferenceUp).magnitude < Epsilon) curState.RawOrientation = Quaternion.FromToRotation(Vector3.forward, dir); else curState.RawOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp); } } } } }