Brak opisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AdaptivePerformanceManagerSettings.cs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Runtime.CompilerServices;
  6. using UnityEditor;
  7. using UnityEngine;
  8. using UnityEngine.Rendering;
  9. using UnityEngine.UIElements;
  10. using UnityEngine.Serialization;
  11. [assembly: InternalsVisibleTo("Unity.AdaptivePerformance.Tests")]
  12. [assembly: InternalsVisibleTo("Unity.AdaptivePerformance.Editor.Tests")]
  13. namespace UnityEngine.AdaptivePerformance
  14. {
  15. /// <summary>
  16. /// Class to handle active loader and subsystem management for Adaptive Performance. This class is to be added as a
  17. /// ScriptableObject asset in your project and should only be referenced by an <see cref="AdaptivePerformanceGeneralSettings"/>
  18. /// instance for its use.
  19. ///
  20. /// Given a list of loaders, it will attempt to load each loader in the given order. Unity will use the first
  21. /// loader that is successful and ignore all remaining loaders. The successful loader
  22. /// is accessible through the <see cref="activeLoader"/> property on the manager.
  23. ///
  24. /// Depending on configuration, the <see cref="AdaptivePerformanceGeneralSettings"/> instance will automatically manage the active loader
  25. /// at the correct points in the application lifecycle. You can override certain points in the active loader lifecycle
  26. /// and manually manage them by toggling the <see cref="AdaptivePerformanceManagerSettings.automaticLoading"/> and <see cref="AdaptivePerformanceManagerSettings.automaticRunning"/>
  27. /// properties. Disabling <see cref="AdaptivePerformanceManagerSettings.automaticLoading"/> implies that you are responsible for the full lifecycle
  28. /// of the Adaptive Performance session normally handled by the <see cref="AdaptivePerformanceGeneralSettings"/> instance. Setting this to false also sets
  29. /// <see cref="AdaptivePerformanceManagerSettings.automaticRunning"/> to false.
  30. ///
  31. /// Disabling <see cref="AdaptivePerformanceManagerSettings.automaticRunning"/> only implies that you are responsible for starting and stopping
  32. /// the <see cref="activeLoader"/> through the <see cref="StartSubsystems"/> and <see cref="StopSubsystems"/> APIs.
  33. ///
  34. /// Unity executes atomatic lifecycle management as follows:
  35. ///
  36. /// * 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.
  37. /// * Start calls <see cref="StartSubsystems"/> internally. Ask the active loader to start all subsystems.
  38. /// * OnDisable calls <see cref="StopSubsystems"/> internally. Ask the active loader to stop all subsystems.
  39. /// * OnDestroy calls <see cref="DeinitializeLoader"/> internally. Deinitialize and remove the active loader.
  40. /// </summary>
  41. public sealed class AdaptivePerformanceManagerSettings : ScriptableObject
  42. {
  43. [HideInInspector]
  44. bool m_InitializationComplete = false;
  45. [SerializeField]
  46. [Tooltip("Determines if the Adaptive Performance Manager instance is responsible for creating and destroying the appropriate loader instance.")]
  47. bool m_AutomaticLoading = false;
  48. /// <summary>
  49. /// Get and set Automatic Loading state for this manager. When this is true, the manager will automatically call
  50. /// <see cref="InitializeLoader"/> and <see cref="DeinitializeLoader"/> for you. When false, <see cref="automaticRunning"/>
  51. /// is also set to false and remains that way. This means that disabling automatic loading disables all automatic behavior
  52. /// for the manager.
  53. /// </summary>
  54. public bool automaticLoading
  55. {
  56. get { return m_AutomaticLoading; }
  57. set { m_AutomaticLoading = value; }
  58. }
  59. [SerializeField]
  60. [Tooltip("Determines if the Adaptive Performance Manager instance is responsible for starting and stopping subsystems for the active loader instance.")]
  61. bool m_AutomaticRunning = false;
  62. /// <summary>
  63. /// Get and set the automatic running state for this manager. When this is true, the manager will call <see cref="StartSubsystems"/>
  64. /// and <see cref="StopSubsystems"/> APIs at appropriate times. When false, or when <see cref="automaticLoading"/> is false,
  65. /// it is up to the user of the manager to handle that same functionality.
  66. /// </summary>
  67. public bool automaticRunning
  68. {
  69. get { return m_AutomaticRunning; }
  70. set { m_AutomaticRunning = value; }
  71. }
  72. [SerializeField]
  73. [Tooltip("List of Adaptive Performance Loader instances arranged in desired load order.")]
  74. List<AdaptivePerformanceLoader> m_Loaders = new List<AdaptivePerformanceLoader>();
  75. /// <summary>
  76. /// List of loaders currently managed by this Adaptive Performance Manager instance.
  77. /// </summary>
  78. public List<AdaptivePerformanceLoader> loaders
  79. {
  80. get { return m_Loaders; }
  81. #if UNITY_EDITOR
  82. set { m_Loaders = value; }
  83. #endif
  84. }
  85. /// <summary>
  86. /// Read-only boolean that is true if initialization is completed and false otherwise. Because initialization is
  87. /// handled as a Coroutine, applications that use the auto-lifecycle management of AdaptivePerformanceManager
  88. /// will need to wait for init to complete before checking for an ActiveLoader and calling StartSubsystems.
  89. /// </summary>
  90. public bool isInitializationComplete
  91. {
  92. get { return m_InitializationComplete; }
  93. }
  94. [HideInInspector]
  95. static AdaptivePerformanceLoader s_ActiveLoader = null;
  96. ///<summary>
  97. /// Returns the current singleton active loader instance.
  98. ///</summary>
  99. [HideInInspector]
  100. public AdaptivePerformanceLoader activeLoader { get { return s_ActiveLoader; } private set { s_ActiveLoader = value; } }
  101. /// <summary>
  102. /// Returns the current active loader, cast to the requested type. Useful shortcut when you need
  103. /// to get the active loader as something less generic than AdaptivePerformanceLoader.
  104. /// </summary>
  105. /// <typeparam name="T">Requested type of the loader.</typeparam>
  106. /// <returns>The active loader as requested type, or null if no active loader currently exists.</returns>
  107. public T ActiveLoaderAs<T>() where T : AdaptivePerformanceLoader
  108. {
  109. return activeLoader as T;
  110. }
  111. /// <summary>
  112. /// Iterate over the configured list of loaders and attempt to initialize each one. The first one
  113. /// that succeeds is set as the active loader and initialization immediately terminates.
  114. ///
  115. /// When this completes, <see cref="isInitializationComplete"/> will be set to true. This will mark that it is safe to
  116. /// call other parts of the API, but does not guarantee that init successfully created a loader. To check that init successfully created a loader,
  117. /// you need to check that ActiveLoader is not null.
  118. ///
  119. /// **Note**: There can only be one active loader. Any attempt to initialize a new active loader with one
  120. /// already set will cause a warning to be logged and immediate exit of this function.
  121. ///
  122. /// This method is synchronous and on return all state should be immediately checkable.
  123. /// </summary>
  124. internal void InitializeLoaderSync()
  125. {
  126. if (isInitializationComplete && activeLoader != null)
  127. {
  128. Debug.LogWarning(
  129. "Adaptive Performance Management has already initialized an active loader in this scene." +
  130. "Please make sure to stop all subsystems and deinitialize the active loader before initializing a new one.");
  131. return;
  132. }
  133. foreach (var loader in loaders)
  134. {
  135. if (loader != null)
  136. {
  137. if (loader.Initialize())
  138. {
  139. activeLoader = loader;
  140. m_InitializationComplete = true;
  141. return;
  142. }
  143. }
  144. }
  145. activeLoader = null;
  146. }
  147. /// <summary>
  148. /// Iterate over the configured list of loaders and attempt to initialize each one. The first one
  149. /// that succeeds is set as the active loader and initialization immediately terminates.
  150. ///
  151. /// When complete, <see cref="isInitializationComplete"/> will be set to true. This will mark that it is safe to
  152. /// call other parts of the API, but does not guarantee that init successfully created a loader. To check that init successfully created a loader,
  153. /// you need to check that ActiveLoader is not null.
  154. ///
  155. /// **Note:** There can only be one active loader. Any attempt to initialize a new active loader with one
  156. /// already set will cause a warning to be logged and this function wil immeditely exit.
  157. ///
  158. /// Iteration is done asynchronously. You must call this method within the context of a Coroutine.
  159. /// </summary>
  160. ///
  161. /// <returns>Enumerator marking the next spot to continue execution at.</returns>
  162. internal IEnumerator InitializeLoader()
  163. {
  164. if (isInitializationComplete && activeLoader != null)
  165. {
  166. Debug.LogWarning(
  167. "Adaptive Performance Management has already initialized an active loader in this scene." +
  168. "Please make sure to stop all subsystems and deinitialize the active loader before initializing a new one.");
  169. yield break;
  170. }
  171. foreach (var loader in loaders)
  172. {
  173. if (loader != null)
  174. {
  175. if (loader.Initialize())
  176. {
  177. activeLoader = loader;
  178. m_InitializationComplete = true;
  179. yield break;
  180. }
  181. }
  182. yield return null;
  183. }
  184. activeLoader = null;
  185. }
  186. /// <summary>
  187. /// If there is an active loader, this will request the loader to start all the subsystems that it
  188. /// is managing.
  189. ///
  190. /// You must wait for <see cref="isInitializationComplete"/> to be set to true before calling this API.
  191. /// </summary>
  192. internal void StartSubsystems()
  193. {
  194. if (!m_InitializationComplete)
  195. {
  196. Debug.LogWarning(
  197. "Call to StartSubsystems without an initialized manager." +
  198. "Please make sure to wait for initialization to complete before calling this API.");
  199. return;
  200. }
  201. if (activeLoader == null)
  202. return;
  203. activeLoader.Start();
  204. }
  205. /// <summary>
  206. /// If there is an active loader, this will request the loader to stop all the subsystems that it
  207. /// is managing.
  208. ///
  209. /// You must wait for <see cref="isInitializationComplete"/> to be set to true before calling this API.
  210. /// </summary>
  211. internal void StopSubsystems()
  212. {
  213. if (!m_InitializationComplete)
  214. {
  215. Debug.LogWarning(
  216. "Call to StopSubsystems without an initialized manager." +
  217. "Please make sure to wait for initialization to complete before calling this API.");
  218. return;
  219. }
  220. if (activeLoader == null)
  221. return;
  222. activeLoader.Stop();
  223. }
  224. /// <summary>
  225. /// If there is an active loader, this function will deinitialize it and remove the active loader instance from
  226. /// management. Unity will automatically call <see cref="StopSubsystems"/> before deinitialization to make sure
  227. /// that things are cleaned up appropriately.
  228. ///
  229. /// You must wait for <see cref="isInitializationComplete"/> to be set to true before calling this API.
  230. ///
  231. /// On return, <see cref="isInitializationComplete"/> will be set to false.
  232. /// </summary>
  233. internal void DeinitializeLoader()
  234. {
  235. if (!m_InitializationComplete)
  236. {
  237. Debug.LogWarning(
  238. "Call to DeinitializeLoader without an initialized manager." +
  239. "Please make sure to wait for initialization to complete before calling this API.");
  240. return;
  241. }
  242. StopSubsystems();
  243. if (activeLoader != null)
  244. {
  245. activeLoader.Deinitialize();
  246. activeLoader = null;
  247. }
  248. m_InitializationComplete = false;
  249. }
  250. void OnDisable()
  251. {
  252. // should we have an OnEnable()?
  253. if (automaticLoading && automaticRunning)
  254. {
  255. StopSubsystems();
  256. }
  257. }
  258. void OnDestroy()
  259. {
  260. if (automaticLoading)
  261. {
  262. DeinitializeLoader();
  263. }
  264. }
  265. }
  266. }