using UnityEngine; using UnityEngine.Serialization; namespace Unity.Cinemachine { /// /// An add-on module for Cm Camera that adds a final offset to the camera /// [AddComponentMenu("Cinemachine/Procedural/Extensions/Cinemachine Camera Offset")] [ExecuteAlways] [SaveDuringPlay] [HelpURL(Documentation.BaseURL + "manual/CinemachineCameraOffset.html")] public class CinemachineCameraOffset : CinemachineExtension { /// /// Offset the camera's position by this much (camera space) /// [Tooltip("Offset the camera's position by this much (camera space)")] [FormerlySerializedAs("m_Offset")] public Vector3 Offset = Vector3.zero; /// /// When to apply the offset /// [Tooltip("When to apply the offset")] [FormerlySerializedAs("m_ApplyAfter")] public CinemachineCore.Stage ApplyAfter = CinemachineCore.Stage.Aim; /// /// If applying offset after aim, re-adjust the aim to preserve the screen position /// of the LookAt target as much as possible /// [Tooltip("If applying offset after aim, re-adjust the aim to preserve the screen position" + " of the LookAt target as much as possible")] [FormerlySerializedAs("m_PreserveComposition")] public bool PreserveComposition; private void Reset() { Offset = Vector3.zero; ApplyAfter = CinemachineCore.Stage.Aim; PreserveComposition = false; } /// /// Applies the specified offset to the camera state /// /// The virtual camera being processed /// The current pipeline stage /// The current virtual camera state /// The current applicable deltaTime protected override void PostPipelineStageCallback( CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime) { if (stage == ApplyAfter) { bool preserveAim = PreserveComposition && state.HasLookAt() && stage > CinemachineCore.Stage.Body; Vector3 screenOffset = Vector2.zero; if (preserveAim) { screenOffset = state.RawOrientation.GetCameraRotationToTarget( state.ReferenceLookAt - state.GetCorrectedPosition(), state.ReferenceUp); } Vector3 offset = state.RawOrientation * Offset; state.PositionCorrection += offset; if (!preserveAim) state.ReferenceLookAt += offset; else { var q = Quaternion.LookRotation( state.ReferenceLookAt - state.GetCorrectedPosition(), state.ReferenceUp); q = q.ApplyCameraRotation(-screenOffset, state.ReferenceUp); state.RawOrientation = q; } } } } }