AsteroidsGameManager.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <copyright file="AsteroidsGameManager.cs" company="Exit Games GmbH">
  3. // Part of: Asteroid demo
  4. // </copyright>
  5. // <summary>
  6. // Game Manager for the Asteroid Demo
  7. // </summary>
  8. // <author>developer@exitgames.com</author>
  9. // --------------------------------------------------------------------------------------------------------------------
  10. using System.Collections;
  11. using UnityEngine;
  12. using UnityEngine.UI;
  13. using Photon.Realtime;
  14. using Photon.Pun.UtilityScripts;
  15. using Hashtable = ExitGames.Client.Photon.Hashtable;
  16. namespace Photon.Pun.Demo.Asteroids
  17. {
  18. public class AsteroidsGameManager : MonoBehaviourPunCallbacks
  19. {
  20. public static AsteroidsGameManager Instance = null;
  21. public Text InfoText;
  22. public GameObject[] AsteroidPrefabs;
  23. #region UNITY
  24. public void Awake()
  25. {
  26. Instance = this;
  27. }
  28. public override void OnEnable()
  29. {
  30. base.OnEnable();
  31. CountdownTimer.OnCountdownTimerHasExpired += OnCountdownTimerIsExpired;
  32. }
  33. public void Start()
  34. {
  35. Hashtable props = new Hashtable
  36. {
  37. {AsteroidsGame.PLAYER_LOADED_LEVEL, true}
  38. };
  39. PhotonNetwork.LocalPlayer.SetCustomProperties(props);
  40. }
  41. public override void OnDisable()
  42. {
  43. base.OnDisable();
  44. CountdownTimer.OnCountdownTimerHasExpired -= OnCountdownTimerIsExpired;
  45. }
  46. #endregion
  47. #region COROUTINES
  48. private IEnumerator SpawnAsteroid()
  49. {
  50. while (true)
  51. {
  52. yield return new WaitForSeconds(Random.Range(AsteroidsGame.ASTEROIDS_MIN_SPAWN_TIME, AsteroidsGame.ASTEROIDS_MAX_SPAWN_TIME));
  53. Vector2 direction = Random.insideUnitCircle;
  54. Vector3 position = Vector3.zero;
  55. if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
  56. {
  57. // Make it appear on the left/right side
  58. position = new Vector3(Mathf.Sign(direction.x) * Camera.main.orthographicSize * Camera.main.aspect, 0, direction.y * Camera.main.orthographicSize);
  59. }
  60. else
  61. {
  62. // Make it appear on the top/bottom
  63. position = new Vector3(direction.x * Camera.main.orthographicSize * Camera.main.aspect, 0, Mathf.Sign(direction.y) * Camera.main.orthographicSize);
  64. }
  65. // Offset slightly so we are not out of screen at creation time (as it would destroy the asteroid right away)
  66. position -= position.normalized * 0.1f;
  67. Vector3 force = -position.normalized * 1000.0f;
  68. Vector3 torque = Random.insideUnitSphere * Random.Range(500.0f, 1500.0f);
  69. object[] instantiationData = {force, torque, true};
  70. PhotonNetwork.InstantiateRoomObject("BigAsteroid", position, Quaternion.Euler(Random.value * 360.0f, Random.value * 360.0f, Random.value * 360.0f), 0, instantiationData);
  71. }
  72. }
  73. private IEnumerator EndOfGame(string winner, int score)
  74. {
  75. float timer = 5.0f;
  76. while (timer > 0.0f)
  77. {
  78. InfoText.text = string.Format("Player {0} won with {1} points.\n\n\nReturning to login screen in {2} seconds.", winner, score, timer.ToString("n2"));
  79. yield return new WaitForEndOfFrame();
  80. timer -= Time.deltaTime;
  81. }
  82. PhotonNetwork.LeaveRoom();
  83. }
  84. #endregion
  85. #region PUN CALLBACKS
  86. public override void OnDisconnected(DisconnectCause cause)
  87. {
  88. UnityEngine.SceneManagement.SceneManager.LoadScene("DemoAsteroids-LobbyScene");
  89. }
  90. public override void OnLeftRoom()
  91. {
  92. PhotonNetwork.Disconnect();
  93. }
  94. public override void OnMasterClientSwitched(Player newMasterClient)
  95. {
  96. if (PhotonNetwork.LocalPlayer.ActorNumber == newMasterClient.ActorNumber)
  97. {
  98. StartCoroutine(SpawnAsteroid());
  99. }
  100. }
  101. public override void OnPlayerLeftRoom(Player otherPlayer)
  102. {
  103. CheckEndOfGame();
  104. }
  105. public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
  106. {
  107. if (changedProps.ContainsKey(AsteroidsGame.PLAYER_LIVES))
  108. {
  109. CheckEndOfGame();
  110. return;
  111. }
  112. if (!PhotonNetwork.IsMasterClient)
  113. {
  114. return;
  115. }
  116. // if there was no countdown yet, the master client (this one) waits until everyone loaded the level and sets a timer start
  117. int startTimestamp;
  118. bool startTimeIsSet = CountdownTimer.TryGetStartTime(out startTimestamp);
  119. if (changedProps.ContainsKey(AsteroidsGame.PLAYER_LOADED_LEVEL))
  120. {
  121. if (CheckAllPlayerLoadedLevel())
  122. {
  123. if (!startTimeIsSet)
  124. {
  125. CountdownTimer.SetStartTime();
  126. }
  127. }
  128. else
  129. {
  130. // not all players loaded yet. wait:
  131. Debug.Log("setting text waiting for players! ",this.InfoText);
  132. InfoText.text = "Waiting for other players...";
  133. }
  134. }
  135. }
  136. #endregion
  137. // called by OnCountdownTimerIsExpired() when the timer ended
  138. private void StartGame()
  139. {
  140. Debug.Log("StartGame!");
  141. // on rejoin, we have to figure out if the spaceship exists or not
  142. // if this is a rejoin (the ship is already network instantiated and will be setup via event) we don't need to call PN.Instantiate
  143. float angularStart = (360.0f / PhotonNetwork.CurrentRoom.PlayerCount) * PhotonNetwork.LocalPlayer.GetPlayerNumber();
  144. float x = 20.0f * Mathf.Sin(angularStart * Mathf.Deg2Rad);
  145. float z = 20.0f * Mathf.Cos(angularStart * Mathf.Deg2Rad);
  146. Vector3 position = new Vector3(x, 0.0f, z);
  147. Quaternion rotation = Quaternion.Euler(0.0f, angularStart, 0.0f);
  148. PhotonNetwork.Instantiate("Spaceship", position, rotation, 0); // avoid this call on rejoin (ship was network instantiated before)
  149. if (PhotonNetwork.IsMasterClient)
  150. {
  151. StartCoroutine(SpawnAsteroid());
  152. }
  153. }
  154. private bool CheckAllPlayerLoadedLevel()
  155. {
  156. foreach (Player p in PhotonNetwork.PlayerList)
  157. {
  158. object playerLoadedLevel;
  159. if (p.CustomProperties.TryGetValue(AsteroidsGame.PLAYER_LOADED_LEVEL, out playerLoadedLevel))
  160. {
  161. if ((bool) playerLoadedLevel)
  162. {
  163. continue;
  164. }
  165. }
  166. return false;
  167. }
  168. return true;
  169. }
  170. private void CheckEndOfGame()
  171. {
  172. bool allDestroyed = true;
  173. foreach (Player p in PhotonNetwork.PlayerList)
  174. {
  175. object lives;
  176. if (p.CustomProperties.TryGetValue(AsteroidsGame.PLAYER_LIVES, out lives))
  177. {
  178. if ((int) lives > 0)
  179. {
  180. allDestroyed = false;
  181. break;
  182. }
  183. }
  184. }
  185. if (allDestroyed)
  186. {
  187. if (PhotonNetwork.IsMasterClient)
  188. {
  189. StopAllCoroutines();
  190. }
  191. string winner = "";
  192. int score = -1;
  193. foreach (Player p in PhotonNetwork.PlayerList)
  194. {
  195. if (p.GetScore() > score)
  196. {
  197. winner = p.NickName;
  198. score = p.GetScore();
  199. }
  200. }
  201. StartCoroutine(EndOfGame(winner, score));
  202. }
  203. }
  204. private void OnCountdownTimerIsExpired()
  205. {
  206. StartGame();
  207. }
  208. }
  209. }