_FrameRequestComponent.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System.Collections;
  2. using UnityEngine;
  3. namespace UnityEditor.Recorder
  4. {
  5. /// <summary>
  6. /// Base component used for requesting a new frame. This class uses coroutines and WaitForEndOfFrame.
  7. /// This will not accumulate requests. All requests for the same frame will be merged into one request.
  8. /// Thus, FrameReady will be called once.
  9. /// This class pauses the project simulation (updates), waiting for the GPU to be ready.
  10. /// </summary>
  11. abstract class _FrameRequestComponent : MonoBehaviour
  12. {
  13. protected enum State
  14. {
  15. WaitingForFirstFrame,
  16. Running
  17. }
  18. /// <summary>
  19. /// Used to cache project's Time.TimeScale.
  20. /// </summary>
  21. private float projectTimeScale = 0;
  22. /// <summary>
  23. /// Number of requests submitted to record a frame from LateUpdate.
  24. /// This value shouldn't go over producedCount+1 or we would be requesting
  25. /// too many frames at the same time and end up with copies.
  26. /// </summary>
  27. protected int requestCount = 0;
  28. /// <summary>
  29. /// Number of frame we did record in our coroutine.
  30. /// </summary>
  31. protected int frameProducedCount = 0;
  32. /// <summary>
  33. /// Component current state.
  34. /// </summary>
  35. protected State currentState;
  36. protected virtual void Awake()
  37. {
  38. requestCount = frameProducedCount = 0;
  39. EnterWaitingForFirstFrameState();
  40. }
  41. protected virtual void RequestNewFrame()
  42. {
  43. if (frameProducedCount == requestCount)
  44. {
  45. StartCoroutine(FrameRequest());
  46. requestCount++;
  47. }
  48. }
  49. protected virtual void OnDestroy()
  50. {
  51. // Restore timescale if we exit playmode before we had
  52. // time to restore it after first frame is rendered.
  53. if (currentState == State.WaitingForFirstFrame)
  54. RestoreProjectTimeScale();
  55. }
  56. protected abstract void FrameReady();
  57. IEnumerator FrameRequest()
  58. {
  59. yield return new WaitForEndOfFrame();
  60. FrameReady();
  61. if (currentState == State.WaitingForFirstFrame)
  62. EnterRunningState();
  63. frameProducedCount++;
  64. }
  65. void SaveProjectTimeScale()
  66. {
  67. projectTimeScale = Time.timeScale;
  68. Time.timeScale = 0f;
  69. }
  70. void RestoreProjectTimeScale()
  71. {
  72. if (Time.timeScale == 0)
  73. Time.timeScale = projectTimeScale;
  74. }
  75. void EnterWaitingForFirstFrameState()
  76. {
  77. currentState = State.WaitingForFirstFrame;
  78. SaveProjectTimeScale();
  79. }
  80. void EnterRunningState()
  81. {
  82. currentState = State.Running;
  83. RestoreProjectTimeScale();
  84. }
  85. }
  86. }