123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.CompilerServices;
-
- using UnityEditor;
-
- using UnityEngine;
- using UnityEngine.Rendering;
- using UnityEngine.UIElements;
- using UnityEngine.Serialization;
-
- [assembly: InternalsVisibleTo("Unity.AdaptivePerformance.Tests")]
- namespace UnityEngine.AdaptivePerformance
- {
- /// <summary>
- /// Class to handle active loader and subsystem management for Adaptive Performance. This class is to be added as a
- /// ScriptableObject asset in your project and should only be referenced by an <see cref="AdaptivePerformanceGeneralSettings"/>
- /// instance for its use.
- ///
- /// Given a list of loaders, it will attempt to load each loader in the given order. Unity will use the first
- /// loader that is successful and ignore all remaining loaders. The successful loader
- /// is accessible through the <see cref="activeLoader"/> property on the manager.
- ///
- /// Depending on configuration, the <see cref="AdaptivePerformanceGeneralSettings"/> instance will automatically manage the active loader
- /// at the correct points in the application lifecycle. You can override certain points in the active loader lifecycle
- /// and manually manage them by toggling the <see cref="AdaptivePerformanceManagerSettings.automaticLoading"/> and <see cref="AdaptivePerformanceManagerSettings.automaticRunning"/>
- /// properties. Disabling <see cref="AdaptivePerformanceManagerSettings.automaticLoading"/> implies that you are responsible for the full lifecycle
- /// of the Adaptive Performance session normally handled by the <see cref="AdaptivePerformanceGeneralSettings"/> instance. Setting this to false also sets
- /// <see cref="AdaptivePerformanceManagerSettings.automaticRunning"/> to false.
- ///
- /// Disabling <see cref="AdaptivePerformanceManagerSettings.automaticRunning"/> only implies that you are responsible for starting and stopping
- /// the <see cref="activeLoader"/> through the <see cref="StartSubsystems"/> and <see cref="StopSubsystems"/> APIs.
- ///
- /// Unity executes atomatic lifecycle management as follows:
- ///
- /// * OnEnable calls <see cref="InitializeLoader"/> internally. The loader list will be iterated over and the first successful loader will be set as the active loader.
- /// * Start calls <see cref="StartSubsystems"/> internally. Ask the active loader to start all subsystems.
- /// * OnDisable calls <see cref="StopSubsystems"/> internally. Ask the active loader to stop all subsystems.
- /// * OnDestroy calls <see cref="DeinitializeLoader"/> internally. Deinitialize and remove the active loader.
- /// </summary>
- public sealed class AdaptivePerformanceManagerSettings : ScriptableObject
- {
- [HideInInspector]
- bool m_InitializationComplete = false;
-
- [SerializeField]
- [Tooltip("Determines if the Adaptive Performance Manager instance is responsible for creating and destroying the appropriate loader instance.")]
- bool m_AutomaticLoading = false;
-
- /// <summary>
- /// Get and set Automatic Loading state for this manager. When this is true, the manager will automatically call
- /// <see cref="InitializeLoader"/> and <see cref="DeinitializeLoader"/> for you. When false, <see cref="automaticRunning"/>
- /// is also set to false and remains that way. This means that disabling automatic loading disables all automatic behavior
- /// for the manager.
- /// </summary>
- public bool automaticLoading
- {
- get { return m_AutomaticLoading; }
- set { m_AutomaticLoading = value; }
- }
-
- [SerializeField]
- [Tooltip("Determines if the Adaptive Performance Manager instance is responsible for starting and stopping subsystems for the active loader instance.")]
- bool m_AutomaticRunning = false;
-
- /// <summary>
- /// Get and set the automatic running state for this manager. When this is true, the manager will call <see cref="StartSubsystems"/>
- /// and <see cref="StopSubsystems"/> APIs at appropriate times. When false, or when <see cref="automaticLoading"/> is false,
- /// it is up to the user of the manager to handle that same functionality.
- /// </summary>
- public bool automaticRunning
- {
- get { return m_AutomaticRunning; }
- set { m_AutomaticRunning = value; }
- }
-
-
- [SerializeField]
- [Tooltip("List of Adaptive Performance Loader instances arranged in desired load order.")]
- List<AdaptivePerformanceLoader> m_Loaders = new List<AdaptivePerformanceLoader>();
-
- /// <summary>
- /// List of loaders currently managed by this Adaptive Performance Manager instance.
- /// </summary>
- public List<AdaptivePerformanceLoader> loaders
- {
- get { return m_Loaders; }
- #if UNITY_EDITOR
- set { m_Loaders = value; }
- #endif
- }
-
-
- /// <summary>
- /// Read-only boolean that is true if initialization is completed and false otherwise. Because initialization is
- /// handled as a Coroutine, applications that use the auto-lifecycle management of AdaptivePerformanceManager
- /// will need to wait for init to complete before checking for an ActiveLoader and calling StartSubsystems.
- /// </summary>
- public bool isInitializationComplete
- {
- get { return m_InitializationComplete; }
- }
-
- [HideInInspector]
- static AdaptivePerformanceLoader s_ActiveLoader = null;
-
- ///<summary>
- /// Returns the current singleton active loader instance.
- ///</summary>
- [HideInInspector]
- public AdaptivePerformanceLoader activeLoader { get { return s_ActiveLoader; } private set { s_ActiveLoader = value; } }
-
- /// <summary>
- /// Returns the current active loader, cast to the requested type. Useful shortcut when you need
- /// to get the active loader as something less generic than AdaptivePerformanceLoader.
- /// </summary>
- /// <typeparam name="T">Requested type of the loader.</typeparam>
- /// <returns>The active loader as requested type, or null if no active loader currently exists.</returns>
- public T ActiveLoaderAs<T>() where T : AdaptivePerformanceLoader
- {
- return activeLoader as T;
- }
-
- /// <summary>
- /// Iterate over the configured list of loaders and attempt to initialize each one. The first one
- /// that succeeds is set as the active loader and initialization immediately terminates.
- ///
- /// When this completes, <see cref="isInitializationComplete"/> will be set to true. This will mark that it is safe to
- /// call other parts of the API, but does not guarantee that init successfully created a loader. To check that init successfully created a loader,
- /// you need to check that ActiveLoader is not null.
- ///
- /// **Note**: There can only be one active loader. Any attempt to initialize a new active loader with one
- /// already set will cause a warning to be logged and immediate exit of this function.
- ///
- /// This method is synchronous and on return all state should be immediately checkable.
- /// </summary>
- public void InitializeLoaderSync()
- {
- if (isInitializationComplete && activeLoader != null)
- {
- Debug.LogWarning(
- "Adaptive Performance Management has already initialized an active loader in this scene." +
- "Please make sure to stop all subsystems and deinitialize the active loader before initializing a new one.");
- return;
- }
-
- foreach (var loader in loaders)
- {
- if (loader != null)
- {
- if (loader.Initialize())
- {
- activeLoader = loader;
- m_InitializationComplete = true;
- return;
- }
- }
- }
-
- activeLoader = null;
- }
-
- /// <summary>
- /// Iterate over the configured list of loaders and attempt to initialize each one. The first one
- /// that succeeds is set as the active loader and initialization immediately terminates.
- ///
- /// When complete, <see cref="isInitializationComplete"/> will be set to true. This will mark that it is safe to
- /// call other parts of the API, but does not guarantee that init successfully created a loader. To check that init successfully created a loader,
- /// you need to check that ActiveLoader is not null.
- ///
- /// **Note:** There can only be one active loader. Any attempt to initialize a new active loader with one
- /// already set will cause a warning to be logged and this function wil immeditely exit.
- ///
- /// Iteration is done asynchronously. You must call this method within the context of a Coroutine.
- /// </summary>
- ///
- /// <returns>Enumerator marking the next spot to continue execution at.</returns>
- public IEnumerator InitializeLoader()
- {
- if (isInitializationComplete && activeLoader != null)
- {
- Debug.LogWarning(
- "Adaptive Performance Management has already initialized an active loader in this scene." +
- "Please make sure to stop all subsystems and deinitialize the active loader before initializing a new one.");
- yield break;
- }
-
- foreach (var loader in loaders)
- {
- if (loader != null)
- {
- if (loader.Initialize())
- {
- activeLoader = loader;
- m_InitializationComplete = true;
- yield break;
- }
- }
-
- yield return null;
- }
-
- activeLoader = null;
- }
-
- /// <summary>
- /// If there is an active loader, this will request the loader to start all the subsystems that it
- /// is managing.
- ///
- /// You must wait for <see cref="isInitializationComplete"/> to be set to true before calling this API.
- /// </summary>
- public void StartSubsystems()
- {
- if (!m_InitializationComplete)
- {
- Debug.LogWarning(
- "Call to StartSubsystems without an initialized manager." +
- "Please make sure to wait for initialization to complete before calling this API.");
- return;
- }
-
- if (activeLoader != null)
- {
- activeLoader.Start();
- }
- }
-
- /// <summary>
- /// If there is an active loader, this will request the loader to stop all the subsystems that it
- /// is managing.
- ///
- /// You must wait for <see cref="isInitializationComplete"/> to be set to true before calling this API.
- /// </summary>
- public void StopSubsystems()
- {
- if (!m_InitializationComplete)
- {
- Debug.LogWarning(
- "Call to StopSubsystems without an initialized manager." +
- "Please make sure to wait for initialization to complete before calling this API.");
- return;
- }
-
- if (activeLoader != null)
- {
- activeLoader.Stop();
- }
- }
-
- /// <summary>
- /// If there is an active loader, this function will deinitialize it and remove the active loader instance from
- /// management. Unity will automatically call <see cref="StopSubsystems"/> before deinitialization to make sure
- /// that things are cleaned up appropriately.
- ///
- /// You must wait for <see cref="isInitializationComplete"/> to be set to true before calling this API.
- ///
- /// On return, <see cref="isInitializationComplete"/> will be set to false.
- /// </summary>
- public void DeinitializeLoader()
- {
- if (!m_InitializationComplete)
- {
- Debug.LogWarning(
- "Call to DeinitializeLoader without an initialized manager." +
- "Please make sure to wait for initialization to complete before calling this API.");
- return;
- }
-
- StopSubsystems();
- if (activeLoader != null)
- {
- activeLoader.Deinitialize();
- activeLoader = null;
- }
-
- m_InitializationComplete = false;
- }
-
- // Use this for initialization
- void Start()
- {
- if (automaticLoading && automaticRunning)
- {
- StartSubsystems();
- }
- }
-
- void OnDisable()
- {
- if (automaticLoading && automaticRunning)
- {
- StopSubsystems();
- }
- }
-
- void OnDestroy()
- {
- if (automaticLoading)
- {
- DeinitializeLoader();
- }
- }
- }
- }
|