using System.Collections; using UnityEngine; namespace UnityEditor.Recorder { /// /// Base component used for requesting a new frame. This class uses coroutines and WaitForEndOfFrame. /// This will not accumulate requests. All requests for the same frame will be merged into one request. /// Thus, FrameReady will be called once. /// This class pauses the project simulation (updates), waiting for the GPU to be ready. /// abstract class _FrameRequestComponent : MonoBehaviour { protected enum State { WaitingForFirstFrame, Running } /// /// Used to cache project's Time.TimeScale. /// private float projectTimeScale = 0; /// /// Number of requests submitted to record a frame from LateUpdate. /// This value shouldn't go over producedCount+1 or we would be requesting /// too many frames at the same time and end up with copies. /// protected int requestCount = 0; /// /// Number of frame we did record in our coroutine. /// protected int frameProducedCount = 0; /// /// Component current state. /// protected State currentState; protected virtual void Awake() { requestCount = frameProducedCount = 0; EnterWaitingForFirstFrameState(); } protected virtual void RequestNewFrame() { if (frameProducedCount == requestCount) { StartCoroutine(FrameRequest()); requestCount++; } } protected virtual void OnDestroy() { // Restore timescale if we exit playmode before we had // time to restore it after first frame is rendered. if (currentState == State.WaitingForFirstFrame) RestoreProjectTimeScale(); } protected abstract void FrameReady(); IEnumerator FrameRequest() { yield return new WaitForEndOfFrame(); FrameReady(); if (currentState == State.WaitingForFirstFrame) EnterRunningState(); frameProducedCount++; } void SaveProjectTimeScale() { projectTimeScale = Time.timeScale; Time.timeScale = 0f; } void RestoreProjectTimeScale() { if (Time.timeScale == 0) Time.timeScale = projectTimeScale; } void EnterWaitingForFirstFrameState() { currentState = State.WaitingForFirstFrame; SaveProjectTimeScale(); } void EnterRunningState() { currentState = State.Running; RestoreProjectTimeScale(); } } }