using UnityEngine; using Cinemachine.Utility; using Cinemachine; /// /// An add-on module for Cinemachine Virtual Camera that adds a final offset to the camera /// [AddComponentMenu("")] // Hide in menu [ExecuteAlways] [HelpURL(Documentation.BaseURL + "api/Cinemachine.CinemachineCameraOffset.html")] [SaveDuringPlay] 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)")] public Vector3 m_Offset = Vector3.zero; /// /// When to apply the offset /// [Tooltip("When to apply the offset")] public CinemachineCore.Stage m_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")] public bool m_PreserveComposition; /// /// 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 == m_ApplyAfter) { bool preserveAim = m_PreserveComposition && state.HasLookAt && stage > CinemachineCore.Stage.Body; Vector3 screenOffset = Vector2.zero; if (preserveAim) { screenOffset = state.RawOrientation.GetCameraRotationToTarget( state.ReferenceLookAt - state.CorrectedPosition, state.ReferenceUp); } Vector3 offset = state.RawOrientation * m_Offset; state.PositionCorrection += offset; if (!preserveAim) state.ReferenceLookAt += offset; else { var q = Quaternion.LookRotation( state.ReferenceLookAt - state.CorrectedPosition, state.ReferenceUp); q = q.ApplyCameraRotation(-screenOffset, state.ReferenceUp); state.RawOrientation = q; } } } }