namespace Zinnia.Process.Moment { using UnityEngine; using UnityEngine.Rendering; using Zinnia.Extension; using Zinnia.Process.Moment.Collection; /// /// Iterates through a given collection and executes the method on the given Unity game loop moment. /// public class MomentProcessor : MonoBehaviour, IProcessable { /// /// The point in the Unity game loop when to execute the processes. /// public enum Moment { /// /// Executes the processes only when the method is called. /// None, /// /// Execute the processes in the FixedUpdate physics part of the Unity game loop. /// FixedUpdate, /// /// Executes the processes in the Update game logic part of the Unity game loop. /// Update, /// /// Executes the processes in the LateUpdate game logic part of the Unity game loop. /// LateUpdate, /// /// Executes the processes in the camera PreCull scene rendering part of the Unity game loop. /// PreCull, /// /// Executes the processes in the camera PreRender scene rendering part of the Unity game loop. /// PreRender, /// /// Executes the processes in the Application BeforeRender scene rendering part of the Unity game loop. /// BeforeRender } [Tooltip("The moment in which to process the given processes.")] [SerializeField] private Moment processMoment = Moment.PreRender; /// /// The moment in which to process the given processes. /// public Moment ProcessMoment { get { return processMoment; } set { if (this.IsMemberChangeAllowed()) { OnBeforeProcessMomentChange(); } processMoment = value; if (this.IsMemberChangeAllowed()) { OnAfterProcessMomentChange(); } } } [Tooltip("A collection of MomentProcess to process.")] [SerializeField] private MomentProcessObservableList processes; /// /// A collection of to process. /// public MomentProcessObservableList Processes { get { return processes; } set { processes = value; } } /// /// Sets the . /// /// The index of the . public virtual void SetProcessMoment(int index) { ProcessMoment = EnumExtensions.GetByIndex(index); } /// public virtual void Process() { ProcessMoments(); } protected virtual void OnEnable() { SubscribeMoment(); } protected virtual void OnDisable() { UnsubscribeMoment(); } protected virtual void FixedUpdate() { if (ProcessMoment == Moment.FixedUpdate) { ProcessMoments(); } } protected virtual void Update() { if (ProcessMoment == Moment.Update) { ProcessMoments(); } } protected virtual void LateUpdate() { if (ProcessMoment == Moment.LateUpdate) { ProcessMoments(); } } #if UNITY_2019_1_OR_NEWER protected virtual void OnSrpCameraPreRender(ScriptableRenderContext context, Camera givenCamera) { Process(); } #endif protected virtual void OnCameraPreRender(Camera givenCamera) { ProcessMoments(); } protected virtual void OnCameraPreCull(Camera givenCamera) { ProcessMoments(); } protected virtual void OnApplicationBeforeRender() { ProcessMoments(); } /// /// Handles unsubscribing to the chosen subscribed moment event. /// protected virtual void UnsubscribeMoment() { switch (ProcessMoment) { case Moment.PreRender: if (GraphicsSettings.renderPipelineAsset != null) { #if UNITY_2019_1_OR_NEWER RenderPipelineManager.beginCameraRendering -= OnSrpCameraPreRender; #endif } else { Camera.onPreRender -= OnCameraPreRender; } break; case Moment.PreCull: Camera.onPreCull -= OnCameraPreCull; break; case Moment.BeforeRender: Application.onBeforeRender -= OnApplicationBeforeRender; break; } } /// /// Handles subscribing to the chosen moment to process event. /// protected virtual void SubscribeMoment() { switch (ProcessMoment) { case Moment.PreRender: if (GraphicsSettings.renderPipelineAsset != null) { #if UNITY_2019_1_OR_NEWER RenderPipelineManager.beginCameraRendering += OnSrpCameraPreRender; #else Debug.LogWarning("SRP is only supported on Unity 2019.1 or above"); #endif } else { Camera.onPreRender += OnCameraPreRender; } break; case Moment.PreCull: Camera.onPreCull += OnCameraPreCull; break; case Moment.BeforeRender: Application.onBeforeRender += OnApplicationBeforeRender; break; } } /// /// Iterates through the given and calls on each one. /// protected virtual void ProcessMoments() { if (Processes == null) { return; } foreach (MomentProcess currentProcess in Processes.NonSubscribableElements) { currentProcess.Process(); } } /// /// Called before has been changed. /// protected virtual void OnBeforeProcessMomentChange() { UnsubscribeMoment(); } /// /// Called after has been changed. /// protected virtual void OnAfterProcessMomentChange() { SubscribeMoment(); } } }