private void ProcessActiveCamera(float deltaTime) { // This condition should never occur, but let's be defensive if (!isActiveAndEnabled) { mActiveCameraPreviousFrame = null; mOutgoingCameraPreviousFrame = null; mPreviousFrameWasOverride = false; return; } //UnityEngine.Profiling.Profiler.BeginSample("CinemachineBrain.ProcessActiveCamera"); OverrideStackFrame activeOverride = GetActiveOverride(); ICinemachineCamera activeCamera = ActiveVirtualCamera; if (activeCamera == null) { mOutgoingCameraPreviousFrame = null; } else { // If there is an override, we kill the in-game blend if (activeOverride != null) { mActiveBlend = null; } CinemachineBlend activeBlend = ActiveBlend; // Check for unexpected deletion of the cached mActiveCameraPreviousFrame if (mActiveCameraPreviousFrame != null && mActiveCameraPreviousFrame.VirtualCameraGameObject == null) { mActiveCameraPreviousFrame = null; } // Are we transitioning cameras? if (mActiveCameraPreviousFrame != activeCamera) { // Do we need to create a game-play blend? if (mActiveCameraPreviousFrame != null && !mPreviousFrameWasOverride && activeOverride == null && deltaTime >= 0) { // Create a blend (will be null if a cut) activeBlend = CreateBlend( mActiveCameraPreviousFrame, activeCamera, LookupBlend(mActiveCameraPreviousFrame, activeCamera), mActiveBlend, deltaTime); } // Need this check because Timeline override sometimes inverts outgoing and incoming if (activeCamera != mOutgoingCameraPreviousFrame) { // Notify incoming camera of transition activeCamera.OnTransitionFromCamera(mActiveCameraPreviousFrame, DefaultWorldUp, deltaTime); // If the incoming camera is disabled, then we must assume // that it has not been updated properly if (!activeCamera.VirtualCameraGameObject.activeInHierarchy && (activeBlend == null || !activeBlend.Uses(activeCamera))) { activeCamera.InternalUpdateCameraState(DefaultWorldUp, -1); } if (m_CameraActivatedEvent != null) { m_CameraActivatedEvent.Invoke(activeCamera); } } // If we're cutting without a blend, or no active cameras // were active last frame, send an event if (activeBlend == null || (activeBlend.CamA != mActiveCameraPreviousFrame && activeBlend.CamB != mActiveCameraPreviousFrame && activeBlend.CamA != mOutgoingCameraPreviousFrame && activeBlend.CamB != mOutgoingCameraPreviousFrame)) { if (m_CameraCutEvent != null) { m_CameraCutEvent.Invoke(this); } } } // Advance the current blend (if any) if (activeBlend != null) { if (activeOverride == null) { activeBlend.TimeInBlend += (deltaTime >= 0) ? deltaTime : activeBlend.Duration; } if (activeBlend.IsComplete) { activeBlend = null; } } if (activeOverride == null) { mActiveBlend = activeBlend; } // Apply the result to the Unity camera CameraState state = activeCamera.State; if (activeBlend != null) { state = activeBlend.State; } PushStateToUnityCamera(state, activeCamera); mOutgoingCameraPreviousFrame = null; if (activeBlend != null) { mOutgoingCameraPreviousFrame = activeBlend.CamB; } } mActiveCameraPreviousFrame = activeCamera; mPreviousFrameWasOverride = activeOverride != null; if (mPreviousFrameWasOverride) { // Hack: Because we don't know whether blending in or out... grrr... if (activeOverride.blend != null) { if (activeOverride.blend.BlendWeight < 0.5f) { mActiveCameraPreviousFrame = activeOverride.blend.CamA; mOutgoingCameraPreviousFrame = activeOverride.blend.CamB; } else { mActiveCameraPreviousFrame = activeOverride.blend.CamB; mOutgoingCameraPreviousFrame = activeOverride.blend.CamA; } } } //UnityEngine.Profiling.Profiler.EndSample(); }
/// <summary> /// Update a single Cinemachine Virtual Camera if and only if it /// hasn't already been updated this frame. Always update vcams via this method. /// Calling this more than once per frame for the same camera will have no effect. /// </summary> internal bool UpdateVirtualCamera(ICinemachineCamera vcam, Vector3 worldUp, float deltaTime) { //UnityEngine.Profiling.Profiler.BeginSample("CinemachineCore.UpdateVirtualCamera"); int now = Time.frameCount; UpdateFilter filter = CurrentUpdateFilter; bool isSmartUpdate = filter != UpdateFilter.ForcedFixed && filter != UpdateFilter.ForcedLate; bool isSmartLateUpdate = filter == UpdateFilter.Late; if (!isSmartUpdate) { if (filter == UpdateFilter.ForcedFixed) { filter = UpdateFilter.Fixed; } if (filter == UpdateFilter.ForcedLate) { filter = UpdateFilter.Late; } } if (mUpdateStatus == null) { mUpdateStatus = new Dictionary <ICinemachineCamera, UpdateStatus>(); } if (vcam.VirtualCameraGameObject == null) { if (mUpdateStatus.ContainsKey(vcam)) { mUpdateStatus.Remove(vcam); } //UnityEngine.Profiling.Profiler.EndSample(); return(false); // camera was deleted } UpdateStatus status; if (!mUpdateStatus.TryGetValue(vcam, out status)) { status = new UpdateStatus(now); mUpdateStatus.Add(vcam, status); } int subframes = isSmartLateUpdate ? 1 : CinemachineBrain.GetSubframeCount(); if (status.lastUpdateFrame != now) { status.lastUpdateSubframe = 0; } // If we're in smart update mode and the target moved, then we must examine // how the target has been moving recently in order to figure out whether to // update now bool updateNow = !isSmartUpdate; if (isSmartUpdate) { Matrix4x4 targetPos; if (!GetTargetPosition(vcam, out targetPos)) { updateNow = isSmartLateUpdate; // no target } else { updateNow = status.ChoosePreferredUpdate(now, targetPos, filter) == filter; } } if (updateNow) { status.preferredUpdate = filter; while (status.lastUpdateSubframe < subframes) { //Debug.Log(vcam.Name + ": frame " + Time.frameCount + "." + status.lastUpdateSubframe + ", " + CurrentUpdateFilter + ", deltaTime = " + deltaTime); vcam.InternalUpdateCameraState(worldUp, deltaTime); ++status.lastUpdateSubframe; } status.lastUpdateFrame = now; } mUpdateStatus[vcam] = status; //UnityEngine.Profiling.Profiler.EndSample(); return(true); }