PlayGamesHelperObject.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // <copyright file="PlayGamesHelperObject.cs" company="Google Inc.">
  2. // Copyright (C) 2014 Google Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. // </copyright>
  16. namespace GooglePlayGames.OurUtils
  17. {
  18. using System;
  19. using System.Collections;
  20. using UnityEngine;
  21. using System.Collections.Generic;
  22. public class PlayGamesHelperObject : MonoBehaviour
  23. {
  24. // our (singleton) instance
  25. private static PlayGamesHelperObject instance = null;
  26. // are we a dummy instance (used in the editor?)
  27. private static bool sIsDummy = false;
  28. // queue of actions to run on the game thread
  29. private static List<System.Action> sQueue = new List<Action>();
  30. // member variable used to copy actions from the sQueue and
  31. // execute them on the game thread. It is a member variable
  32. // to help minimize memory allocations.
  33. List<System.Action> localQueue = new List<System.Action>();
  34. // flag that alerts us that we should check the queue
  35. // (we do this just so we don't have to lock() the queue every
  36. // frame to check if it's empty or not).
  37. private volatile static bool sQueueEmpty = true;
  38. // callback for application pause and focus events
  39. private static List<Action<bool>> sPauseCallbackList =
  40. new List<Action<bool>>();
  41. private static List<Action<bool>> sFocusCallbackList =
  42. new List<Action<bool>>();
  43. // Call this once from the game thread
  44. public static void CreateObject()
  45. {
  46. if (instance != null)
  47. {
  48. return;
  49. }
  50. if (Application.isPlaying)
  51. {
  52. // add an invisible game object to the scene
  53. GameObject obj = new GameObject("PlayGames_QueueRunner");
  54. DontDestroyOnLoad(obj);
  55. instance = obj.AddComponent<PlayGamesHelperObject>();
  56. }
  57. else
  58. {
  59. instance = new PlayGamesHelperObject();
  60. sIsDummy = true;
  61. }
  62. }
  63. public void Awake()
  64. {
  65. DontDestroyOnLoad(gameObject);
  66. }
  67. public void OnDisable()
  68. {
  69. if (instance == this)
  70. {
  71. instance = null;
  72. }
  73. }
  74. public static void RunCoroutine(IEnumerator action)
  75. {
  76. if (instance != null)
  77. {
  78. RunOnGameThread(()=>instance.StartCoroutine(action));
  79. }
  80. }
  81. public static void RunOnGameThread(System.Action action)
  82. {
  83. if (action == null)
  84. {
  85. throw new ArgumentNullException("action");
  86. }
  87. if (sIsDummy)
  88. {
  89. return;
  90. }
  91. lock (sQueue)
  92. {
  93. sQueue.Add(action);
  94. sQueueEmpty = false;
  95. }
  96. }
  97. public void Update()
  98. {
  99. if (sIsDummy || sQueueEmpty)
  100. {
  101. return;
  102. }
  103. // first copy the shared queue into a local queue
  104. localQueue.Clear();
  105. lock (sQueue)
  106. {
  107. // transfer the whole queue to our local queue
  108. localQueue.AddRange(sQueue);
  109. sQueue.Clear();
  110. sQueueEmpty = true;
  111. }
  112. // execute queued actions (from local queue)
  113. // use a loop to avoid extra memory allocations using the
  114. // forEach
  115. for (int i = 0; i < localQueue.Count; i++)
  116. {
  117. localQueue[i].Invoke();
  118. }
  119. }
  120. public void OnApplicationFocus(bool focused)
  121. {
  122. foreach (Action<bool> cb in sFocusCallbackList)
  123. {
  124. try
  125. {
  126. cb(focused);
  127. }
  128. catch (Exception e)
  129. {
  130. Debug.LogError("Exception in OnApplicationFocus:" +
  131. e.Message + "\n" + e.StackTrace);
  132. }
  133. }
  134. }
  135. public void OnApplicationPause(bool paused)
  136. {
  137. foreach (Action<bool> cb in sPauseCallbackList)
  138. {
  139. try
  140. {
  141. cb(paused);
  142. }
  143. catch (Exception e)
  144. {
  145. Debug.LogError("Exception in OnApplicationPause:" +
  146. e.Message + "\n" + e.StackTrace);
  147. }
  148. }
  149. }
  150. /// <summary>
  151. /// Adds a callback that is called when the Unity method OnApplicationFocus
  152. /// is called.
  153. /// </summary>
  154. /// <see cref="OnApplicationFocus"/>
  155. /// <param name="callback">Callback.</param>
  156. public static void AddFocusCallback(Action<bool> callback)
  157. {
  158. if (!sFocusCallbackList.Contains(callback))
  159. {
  160. sFocusCallbackList.Add(callback);
  161. }
  162. }
  163. /// <summary>
  164. /// Removes the callback from the list to call when handling OnApplicationFocus
  165. /// is called.
  166. /// </summary>
  167. /// <returns><c>true</c>, if focus callback was removed, <c>false</c> otherwise.</returns>
  168. /// <param name="callback">Callback.</param>
  169. public static bool RemoveFocusCallback(Action<bool> callback)
  170. {
  171. return sFocusCallbackList.Remove(callback);
  172. }
  173. /// <summary>
  174. /// Adds a callback that is called when the Unity method OnApplicationPause
  175. /// is called.
  176. /// </summary>
  177. /// <see cref="OnApplicationPause"/>
  178. /// <param name="callback">Callback.</param>
  179. public static void AddPauseCallback(Action<bool> callback)
  180. {
  181. if (!sPauseCallbackList.Contains(callback))
  182. {
  183. sPauseCallbackList.Add(callback);
  184. }
  185. }
  186. /// <summary>
  187. /// Removes the callback from the list to call when handling OnApplicationPause
  188. /// is called.
  189. /// </summary>
  190. /// <returns><c>true</c>, if focus callback was removed, <c>false</c> otherwise.</returns>
  191. /// <param name="callback">Callback.</param>
  192. public static bool RemovePauseCallback(Action<bool> callback)
  193. {
  194. return sPauseCallbackList.Remove(callback);
  195. }
  196. }
  197. }