HTTPUpdateDelegator.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using UnityEngine;
  2. #if NETFX_CORE
  3. using System.Threading.Tasks;
  4. #endif
  5. namespace BestHTTP
  6. {
  7. /// <summary>
  8. /// Will route some U3D calls to the HTTPManager.
  9. /// </summary>
  10. [ExecuteInEditMode]
  11. [BestHTTP.PlatformSupport.IL2CPP.Il2CppEagerStaticClassConstructionAttribute]
  12. public sealed class HTTPUpdateDelegator : MonoBehaviour
  13. {
  14. #region Public Properties
  15. /// <summary>
  16. /// The singleton instance of the HTTPUpdateDelegator
  17. /// </summary>
  18. public static HTTPUpdateDelegator Instance { get; private set; }
  19. /// <summary>
  20. /// True, if the Instance property should hold a valid value.
  21. /// </summary>
  22. public static bool IsCreated { get; private set; }
  23. /// <summary>
  24. /// Set it true before any CheckInstance() call, or before any request sent to dispatch callbacks on another thread.
  25. /// </summary>
  26. public static bool IsThreaded { get; set; }
  27. /// <summary>
  28. /// It's true if the dispatch thread running.
  29. /// </summary>
  30. public static bool IsThreadRunning { get; private set; }
  31. /// <summary>
  32. /// How much time the plugin should wait between two update call. Its default value 100 ms.
  33. /// </summary>
  34. public static int ThreadFrequencyInMS { get; set; }
  35. /// <summary>
  36. /// Called in the OnApplicationQuit function. If this function returns False, the plugin will not start to
  37. /// shut down itself.
  38. /// </summary>
  39. public static System.Func<bool> OnBeforeApplicationQuit;
  40. public static System.Action<bool> OnApplicationForegroundStateChanged;
  41. #endregion
  42. private static bool IsSetupCalled;
  43. #if UNITY_EDITOR
  44. /// <summary>
  45. /// Called after scene loaded to support Configurable Enter Play Mode (https://docs.unity3d.com/2019.3/Documentation/Manual/ConfigurableEnterPlayMode.html)
  46. /// </summary>
  47. #if UNITY_2019_3_OR_NEWER
  48. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
  49. #endif
  50. static void ResetSetup()
  51. {
  52. IsSetupCalled = false;
  53. HTTPManager.Logger.Information("HTTPUpdateDelegator", "Reset called!");
  54. }
  55. #endif
  56. static HTTPUpdateDelegator()
  57. {
  58. ThreadFrequencyInMS = 100;
  59. }
  60. /// <summary>
  61. /// Will create the HTTPUpdateDelegator instance and set it up.
  62. /// </summary>
  63. public static void CheckInstance()
  64. {
  65. try
  66. {
  67. if (!IsCreated)
  68. {
  69. GameObject go = GameObject.Find("HTTP Update Delegator");
  70. if (go != null)
  71. Instance = go.GetComponent<HTTPUpdateDelegator>();
  72. if (Instance == null)
  73. {
  74. go = new GameObject("HTTP Update Delegator");
  75. go.hideFlags = HideFlags.HideAndDontSave;
  76. Instance = go.AddComponent<HTTPUpdateDelegator>();
  77. }
  78. IsCreated = true;
  79. #if UNITY_EDITOR
  80. if (!UnityEditor.EditorApplication.isPlaying)
  81. {
  82. UnityEditor.EditorApplication.update -= Instance.Update;
  83. UnityEditor.EditorApplication.update += Instance.Update;
  84. }
  85. #if UNITY_2017_2_OR_NEWER
  86. UnityEditor.EditorApplication.playModeStateChanged -= Instance.OnPlayModeStateChanged;
  87. UnityEditor.EditorApplication.playModeStateChanged += Instance.OnPlayModeStateChanged;
  88. #else
  89. UnityEditor.EditorApplication.playmodeStateChanged -= Instance.OnPlayModeStateChanged;
  90. UnityEditor.EditorApplication.playmodeStateChanged += Instance.OnPlayModeStateChanged;
  91. #endif
  92. #endif
  93. HTTPManager.Logger.Information("HTTPUpdateDelegator", "Instance Created!");
  94. }
  95. }
  96. catch
  97. {
  98. HTTPManager.Logger.Error("HTTPUpdateDelegator", "Please call the BestHTTP.HTTPManager.Setup() from one of Unity's event(eg. awake, start) before you send any request!");
  99. }
  100. }
  101. private void Setup()
  102. {
  103. if (IsSetupCalled)
  104. return;
  105. IsSetupCalled = true;
  106. HTTPManager.Setup();
  107. #if UNITY_WEBGL && !UNITY_EDITOR
  108. // Threads are not implemented in WEBGL builds, disable it for now.
  109. IsThreaded = false;
  110. #endif
  111. if (IsThreaded)
  112. PlatformSupport.Threading.ThreadedRunner.RunLongLiving(ThreadFunc);
  113. // Unity doesn't tolerate well if the DontDestroyOnLoad called when purely in editor mode. So, we will set the flag
  114. // only when we are playing, or not in the editor.
  115. if (!Application.isEditor || Application.isPlaying)
  116. GameObject.DontDestroyOnLoad(this.gameObject);
  117. HTTPManager.Logger.Information("HTTPUpdateDelegator", "Setup done!");
  118. }
  119. void ThreadFunc()
  120. {
  121. HTTPManager.Logger.Information ("HTTPUpdateDelegator", "Update Thread Started");
  122. try
  123. {
  124. IsThreadRunning = true;
  125. while (IsThreadRunning)
  126. {
  127. HTTPManager.OnUpdate();
  128. #if NETFX_CORE
  129. await Task.Delay(ThreadFrequencyInMS);
  130. #else
  131. System.Threading.Thread.Sleep(ThreadFrequencyInMS);
  132. #endif
  133. }
  134. }
  135. finally
  136. {
  137. HTTPManager.Logger.Information("HTTPUpdateDelegator", "Update Thread Ended");
  138. }
  139. }
  140. void Update()
  141. {
  142. if (!IsSetupCalled)
  143. Setup();
  144. if (!IsThreaded)
  145. HTTPManager.OnUpdate();
  146. }
  147. #if UNITY_EDITOR
  148. #if UNITY_2017_2_OR_NEWER
  149. void OnPlayModeStateChanged(UnityEditor.PlayModeStateChange playMode)
  150. {
  151. if (playMode == UnityEditor.PlayModeStateChange.EnteredPlayMode)
  152. UnityEditor.EditorApplication.update -= Update;
  153. else if (playMode == UnityEditor.PlayModeStateChange.EnteredEditMode)
  154. {
  155. UnityEditor.EditorApplication.update -= Update;
  156. UnityEditor.EditorApplication.update += Update;
  157. HTTPUpdateDelegator.ResetSetup();
  158. HTTPManager.ResetSetup();
  159. }
  160. }
  161. #else
  162. void OnPlayModeStateChanged()
  163. {
  164. if (UnityEditor.EditorApplication.isPlaying)
  165. UnityEditor.EditorApplication.update -= Update;
  166. else if (!UnityEditor.EditorApplication.isPlaying)
  167. UnityEditor.EditorApplication.update += Update;
  168. }
  169. #endif
  170. #endif
  171. void OnDisable()
  172. {
  173. HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnDisable Called!");
  174. #if UNITY_EDITOR
  175. if (UnityEditor.EditorApplication.isPlaying)
  176. #endif
  177. OnApplicationQuit();
  178. }
  179. void OnApplicationPause(bool isPaused)
  180. {
  181. HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnApplicationPause isPaused: " + isPaused);
  182. if (HTTPUpdateDelegator.OnApplicationForegroundStateChanged != null)
  183. HTTPUpdateDelegator.OnApplicationForegroundStateChanged(isPaused);
  184. }
  185. void OnApplicationQuit()
  186. {
  187. HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnApplicationQuit Called!");
  188. if (OnBeforeApplicationQuit != null)
  189. {
  190. try
  191. {
  192. if (!OnBeforeApplicationQuit())
  193. {
  194. HTTPManager.Logger.Information("HTTPUpdateDelegator", "OnBeforeApplicationQuit call returned false, postponing plugin shutdown.");
  195. return;
  196. }
  197. }
  198. catch(System.Exception ex)
  199. {
  200. HTTPManager.Logger.Exception("HTTPUpdateDelegator", string.Empty, ex);
  201. }
  202. }
  203. IsThreadRunning = false;
  204. if (!IsCreated)
  205. return;
  206. IsCreated = false;
  207. HTTPManager.OnQuit();
  208. }
  209. }
  210. }