/// /// MIT License - Copyright(c) 2019 Ugo Belfiore /// using UnityEngine; namespace PerspectiveSwitcher { /// /// this script contain the logic of the transition between 2 camera /// call ActiveCamera(CameraData cameraData) to activate the one you want /// call StartTransition to see the transition between CameraOne and CameraTwo /// call StartInverseTransition to see the opposite. /// call ResetCamera if you want to reset the projection matrix and the transition /// [RequireComponent(typeof(TransitionInformation)), ExecuteInEditMode] public class PerspectiveSwitcher : MonoBehaviour { [SerializeField, Tooltip("Reference of a Transition")] private TransitionInformation _transitionInformation; [SerializeField, Tooltip("The camera you want to apply the effect")] private Camera _mainCameraRef; private CameraData _prevCameraChoosen; private CameraData _nextCameraChoosen; private FrequencyChrono _frequencyChrono = new FrequencyChrono(); private void Awake() { Init(); } private void Init() { if (_mainCameraRef == null) { _mainCameraRef = Camera.main; } if (_transitionInformation == null) { _transitionInformation = gameObject.GetComponent(); } ActiveCamera(_transitionInformation.CameraOne); } /// /// Active a camera /// /// public void ActiveCamera(CameraData cameraData) { cameraData.Init(); cameraData.SetCameraDatas(_mainCameraRef); } /// /// start the transition from one to two /// [ContextMenu("Start Transition")] public void StartTransition() { ExecuteTransition(_transitionInformation.CameraOne, _transitionInformation.CameraTwo, _transitionInformation.TimeBlend, _mainCameraRef); } /// /// start the transition from two to one /// [ContextMenu("Start Inverse Transition")] public void StartInverseTransition() { ExecuteTransition(_transitionInformation.CameraTwo, _transitionInformation.CameraOne, _transitionInformation.TimeBlend, _mainCameraRef); } /// /// Execute a transition between the first one, and the second one, in timeBlend seconds. /// /// first camera /// second camera /// time of the blend in seconds public void ExecuteTransition(CameraData first, CameraData second, float timeBlend, Camera mainCamera) { _mainCameraRef = mainCamera; _frequencyChrono.StartChrono(timeBlend, false); _prevCameraChoosen = first; _nextCameraChoosen = second; _prevCameraChoosen.Init(); _nextCameraChoosen.Init(); _prevCameraChoosen.SetCameraDatas(_mainCameraRef); } [ContextMenu("Reset Camera")] public void ResetTransition() { _mainCameraRef.ResetProjectionMatrix(); _frequencyChrono.Reset(); } /// /// called even in play mode thanks to [ExecuteInEditMode] /// private void Update() { DoTransition(); } /// /// called every update, do the transition if the timer is ready /// private void DoTransition() { SetFinalCameraIfChronoIsFinished(); EvaluateLerpTransition(); } /// /// called one, when the chrono is finished /// private void SetFinalCameraIfChronoIsFinished() { if (_frequencyChrono.IsFinished()) { _nextCameraChoosen.SetCameraDatas(_mainCameraRef); } } /// /// called every frame, evaluate the transition between the 2 cameras matrix /// if the chrono is running /// private void EvaluateLerpTransition() { //called every frame the chrono is running if (_frequencyChrono.IsRunning()) { float percentFromTime = _frequencyChrono.GetTimer() * 1 / _frequencyChrono.MaxTime; float evaluateLerp = _transitionInformation.CurveEase.Evaluate(percentFromTime); SetCameraLerp(_prevCameraChoosen, _nextCameraChoosen, evaluateLerp); } } /// /// set the data of the camera from the lerp of 2 cameraDatas /// /// CameraData From /// CameraData To /// time evaluated normalized, between 0 & 1 private void SetCameraLerp(CameraData one, CameraData two, float evaluatedTime) { _mainCameraRef.projectionMatrix = MatrixBlendData.DoMatrixTransition(evaluatedTime, one.Projection.GetSetuppedMatrix(), two.Projection.GetSetuppedMatrix()); } } }