CanvasController.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. namespace Mirror.Examples.MultipleMatch
  7. {
  8. public class CanvasController : MonoBehaviour
  9. {
  10. /// <summary>
  11. /// Match Controllers listen for this to terminate their match and clean up
  12. /// </summary>
  13. public event Action<NetworkConnectionToClient> OnPlayerDisconnected;
  14. /// <summary>
  15. /// Cross-reference of client that created the corresponding match in openMatches below
  16. /// </summary>
  17. internal static readonly Dictionary<NetworkConnectionToClient, Guid> playerMatches = new Dictionary<NetworkConnectionToClient, Guid>();
  18. /// <summary>
  19. /// Open matches that are available for joining
  20. /// </summary>
  21. internal static readonly Dictionary<Guid, MatchInfo> openMatches = new Dictionary<Guid, MatchInfo>();
  22. /// <summary>
  23. /// Network Connections of all players in a match
  24. /// </summary>
  25. internal static readonly Dictionary<Guid, HashSet<NetworkConnectionToClient>> matchConnections = new Dictionary<Guid, HashSet<NetworkConnectionToClient>>();
  26. /// <summary>
  27. /// Player informations by Network Connection
  28. /// </summary>
  29. internal static readonly Dictionary<NetworkConnection, PlayerInfo> playerInfos = new Dictionary<NetworkConnection, PlayerInfo>();
  30. /// <summary>
  31. /// Network Connections that have neither started nor joined a match yet
  32. /// </summary>
  33. internal static readonly List<NetworkConnectionToClient> waitingConnections = new List<NetworkConnectionToClient>();
  34. /// <summary>
  35. /// GUID of a match the local player has created
  36. /// </summary>
  37. internal Guid localPlayerMatch = Guid.Empty;
  38. /// <summary>
  39. /// GUID of a match the local player has joined
  40. /// </summary>
  41. internal Guid localJoinedMatch = Guid.Empty;
  42. /// <summary>
  43. /// GUID of a match the local player has selected in the Toggle Group match list
  44. /// </summary>
  45. internal Guid selectedMatch = Guid.Empty;
  46. // Used in UI for "Player #"
  47. int playerIndex = 1;
  48. [Header("GUI References")]
  49. public GameObject matchList;
  50. public GameObject matchPrefab;
  51. public GameObject matchControllerPrefab;
  52. public Button createButton;
  53. public Button joinButton;
  54. public GameObject lobbyView;
  55. public GameObject roomView;
  56. public RoomGUI roomGUI;
  57. public ToggleGroup toggleGroup;
  58. // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload
  59. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
  60. static void ResetStatics()
  61. {
  62. playerMatches.Clear();
  63. openMatches.Clear();
  64. matchConnections.Clear();
  65. playerInfos.Clear();
  66. waitingConnections.Clear();
  67. }
  68. #region UI Functions
  69. // Called from several places to ensure a clean reset
  70. // - MatchNetworkManager.Awake
  71. // - OnStartServer
  72. // - OnStartClient
  73. // - OnClientDisconnect
  74. // - ResetCanvas
  75. internal void InitializeData()
  76. {
  77. playerMatches.Clear();
  78. openMatches.Clear();
  79. matchConnections.Clear();
  80. waitingConnections.Clear();
  81. localPlayerMatch = Guid.Empty;
  82. localJoinedMatch = Guid.Empty;
  83. }
  84. // Called from OnStopServer and OnStopClient when shutting down
  85. void ResetCanvas()
  86. {
  87. InitializeData();
  88. lobbyView.SetActive(false);
  89. roomView.SetActive(false);
  90. gameObject.SetActive(false);
  91. }
  92. #endregion
  93. #region Button Calls
  94. /// <summary>
  95. /// Called from <see cref="MatchGUI.OnToggleClicked"/>
  96. /// </summary>
  97. /// <param name="matchId"></param>
  98. public void SelectMatch(Guid matchId)
  99. {
  100. if (!NetworkClient.active) return;
  101. if (matchId == Guid.Empty)
  102. {
  103. selectedMatch = Guid.Empty;
  104. joinButton.interactable = false;
  105. }
  106. else
  107. {
  108. if (!openMatches.Keys.Contains(matchId))
  109. {
  110. joinButton.interactable = false;
  111. return;
  112. }
  113. selectedMatch = matchId;
  114. MatchInfo infos = openMatches[matchId];
  115. joinButton.interactable = infos.players < infos.maxPlayers;
  116. }
  117. }
  118. /// <summary>
  119. /// Assigned in inspector to Create button
  120. /// </summary>
  121. public void RequestCreateMatch()
  122. {
  123. if (!NetworkClient.active) return;
  124. NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Create });
  125. }
  126. /// <summary>
  127. /// Assigned in inspector to Join button
  128. /// </summary>
  129. public void RequestJoinMatch()
  130. {
  131. if (!NetworkClient.active || selectedMatch == Guid.Empty) return;
  132. NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Join, matchId = selectedMatch });
  133. }
  134. /// <summary>
  135. /// Assigned in inspector to Leave button
  136. /// </summary>
  137. public void RequestLeaveMatch()
  138. {
  139. if (!NetworkClient.active || localJoinedMatch == Guid.Empty) return;
  140. NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Leave, matchId = localJoinedMatch });
  141. }
  142. /// <summary>
  143. /// Assigned in inspector to Cancel button
  144. /// </summary>
  145. public void RequestCancelMatch()
  146. {
  147. if (!NetworkClient.active || localPlayerMatch == Guid.Empty) return;
  148. NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Cancel });
  149. }
  150. /// <summary>
  151. /// Assigned in inspector to Ready button
  152. /// </summary>
  153. public void RequestReadyChange()
  154. {
  155. if (!NetworkClient.active || (localPlayerMatch == Guid.Empty && localJoinedMatch == Guid.Empty)) return;
  156. Guid matchId = localPlayerMatch == Guid.Empty ? localJoinedMatch : localPlayerMatch;
  157. NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Ready, matchId = matchId });
  158. }
  159. /// <summary>
  160. /// Assigned in inspector to Start button
  161. /// </summary>
  162. public void RequestStartMatch()
  163. {
  164. if (!NetworkClient.active || localPlayerMatch == Guid.Empty) return;
  165. NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Start });
  166. }
  167. /// <summary>
  168. /// Called from <see cref="MatchController.RpcExitGame"/>
  169. /// </summary>
  170. public void OnMatchEnded()
  171. {
  172. if (!NetworkClient.active) return;
  173. localPlayerMatch = Guid.Empty;
  174. localJoinedMatch = Guid.Empty;
  175. ShowLobbyView();
  176. }
  177. /// <summary>
  178. /// Sends updated match list to all waiting connections or just one if specified
  179. /// </summary>
  180. /// <param name="conn"></param>
  181. internal void SendMatchList(NetworkConnectionToClient conn = null)
  182. {
  183. if (!NetworkServer.active) return;
  184. if (conn != null)
  185. {
  186. conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.List, matchInfos = openMatches.Values.ToArray() });
  187. }
  188. else
  189. {
  190. foreach (NetworkConnectionToClient waiter in waitingConnections)
  191. {
  192. waiter.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.List, matchInfos = openMatches.Values.ToArray() });
  193. }
  194. }
  195. }
  196. #endregion
  197. #region Server & Client Callbacks
  198. // Methods in this section are called from MatchNetworkManager's corresponding methods
  199. internal void OnStartServer()
  200. {
  201. if (!NetworkServer.active) return;
  202. InitializeData();
  203. NetworkServer.RegisterHandler<ServerMatchMessage>(OnServerMatchMessage);
  204. }
  205. internal void OnServerReady(NetworkConnectionToClient conn)
  206. {
  207. if (!NetworkServer.active) return;
  208. waitingConnections.Add(conn);
  209. playerInfos.Add(conn, new PlayerInfo { playerIndex = this.playerIndex, ready = false });
  210. playerIndex++;
  211. SendMatchList();
  212. }
  213. internal void OnServerDisconnect(NetworkConnectionToClient conn)
  214. {
  215. if (!NetworkServer.active) return;
  216. // Invoke OnPlayerDisconnected on all instances of MatchController
  217. OnPlayerDisconnected?.Invoke(conn);
  218. Guid matchId;
  219. if (playerMatches.TryGetValue(conn, out matchId))
  220. {
  221. playerMatches.Remove(conn);
  222. openMatches.Remove(matchId);
  223. foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
  224. {
  225. PlayerInfo _playerInfo = playerInfos[playerConn];
  226. _playerInfo.ready = false;
  227. _playerInfo.matchId = Guid.Empty;
  228. playerInfos[playerConn] = _playerInfo;
  229. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
  230. }
  231. }
  232. foreach (KeyValuePair<Guid, HashSet<NetworkConnectionToClient>> kvp in matchConnections)
  233. {
  234. kvp.Value.Remove(conn);
  235. }
  236. PlayerInfo playerInfo = playerInfos[conn];
  237. if (playerInfo.matchId != Guid.Empty)
  238. {
  239. MatchInfo matchInfo;
  240. if (openMatches.TryGetValue(playerInfo.matchId, out matchInfo))
  241. {
  242. matchInfo.players--;
  243. openMatches[playerInfo.matchId] = matchInfo;
  244. }
  245. HashSet<NetworkConnectionToClient> connections;
  246. if (matchConnections.TryGetValue(playerInfo.matchId, out connections))
  247. {
  248. PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
  249. foreach (NetworkConnectionToClient playerConn in matchConnections[playerInfo.matchId])
  250. {
  251. if (playerConn != conn)
  252. {
  253. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
  254. }
  255. }
  256. }
  257. }
  258. SendMatchList();
  259. }
  260. internal void OnStopServer()
  261. {
  262. ResetCanvas();
  263. }
  264. internal void OnClientConnect()
  265. {
  266. playerInfos.Add(NetworkClient.connection, new PlayerInfo { playerIndex = this.playerIndex, ready = false });
  267. }
  268. internal void OnStartClient()
  269. {
  270. if (!NetworkClient.active) return;
  271. InitializeData();
  272. ShowLobbyView();
  273. createButton.gameObject.SetActive(true);
  274. joinButton.gameObject.SetActive(true);
  275. NetworkClient.RegisterHandler<ClientMatchMessage>(OnClientMatchMessage);
  276. }
  277. internal void OnClientDisconnect()
  278. {
  279. if (!NetworkClient.active) return;
  280. InitializeData();
  281. }
  282. internal void OnStopClient()
  283. {
  284. ResetCanvas();
  285. }
  286. #endregion
  287. #region Server Match Message Handlers
  288. void OnServerMatchMessage(NetworkConnectionToClient conn, ServerMatchMessage msg)
  289. {
  290. if (!NetworkServer.active) return;
  291. switch (msg.serverMatchOperation)
  292. {
  293. case ServerMatchOperation.None:
  294. {
  295. Debug.LogWarning("Missing ServerMatchOperation");
  296. break;
  297. }
  298. case ServerMatchOperation.Create:
  299. {
  300. OnServerCreateMatch(conn);
  301. break;
  302. }
  303. case ServerMatchOperation.Cancel:
  304. {
  305. OnServerCancelMatch(conn);
  306. break;
  307. }
  308. case ServerMatchOperation.Start:
  309. {
  310. OnServerStartMatch(conn);
  311. break;
  312. }
  313. case ServerMatchOperation.Join:
  314. {
  315. OnServerJoinMatch(conn, msg.matchId);
  316. break;
  317. }
  318. case ServerMatchOperation.Leave:
  319. {
  320. OnServerLeaveMatch(conn, msg.matchId);
  321. break;
  322. }
  323. case ServerMatchOperation.Ready:
  324. {
  325. OnServerPlayerReady(conn, msg.matchId);
  326. break;
  327. }
  328. }
  329. }
  330. void OnServerPlayerReady(NetworkConnectionToClient conn, Guid matchId)
  331. {
  332. if (!NetworkServer.active) return;
  333. PlayerInfo playerInfo = playerInfos[conn];
  334. playerInfo.ready = !playerInfo.ready;
  335. playerInfos[conn] = playerInfo;
  336. HashSet<NetworkConnectionToClient> connections = matchConnections[matchId];
  337. PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
  338. foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
  339. {
  340. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
  341. }
  342. }
  343. void OnServerLeaveMatch(NetworkConnectionToClient conn, Guid matchId)
  344. {
  345. if (!NetworkServer.active) return;
  346. MatchInfo matchInfo = openMatches[matchId];
  347. matchInfo.players--;
  348. openMatches[matchId] = matchInfo;
  349. PlayerInfo playerInfo = playerInfos[conn];
  350. playerInfo.ready = false;
  351. playerInfo.matchId = Guid.Empty;
  352. playerInfos[conn] = playerInfo;
  353. foreach (KeyValuePair<Guid, HashSet<NetworkConnectionToClient>> kvp in matchConnections)
  354. {
  355. kvp.Value.Remove(conn);
  356. }
  357. HashSet<NetworkConnectionToClient> connections = matchConnections[matchId];
  358. PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
  359. foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
  360. {
  361. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
  362. }
  363. SendMatchList();
  364. conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
  365. }
  366. void OnServerCreateMatch(NetworkConnectionToClient conn)
  367. {
  368. if (!NetworkServer.active || playerMatches.ContainsKey(conn)) return;
  369. Guid newMatchId = Guid.NewGuid();
  370. matchConnections.Add(newMatchId, new HashSet<NetworkConnectionToClient>());
  371. matchConnections[newMatchId].Add(conn);
  372. playerMatches.Add(conn, newMatchId);
  373. openMatches.Add(newMatchId, new MatchInfo { matchId = newMatchId, maxPlayers = 2, players = 1 });
  374. PlayerInfo playerInfo = playerInfos[conn];
  375. playerInfo.ready = false;
  376. playerInfo.matchId = newMatchId;
  377. playerInfos[conn] = playerInfo;
  378. PlayerInfo[] infos = matchConnections[newMatchId].Select(playerConn => playerInfos[playerConn]).ToArray();
  379. conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Created, matchId = newMatchId, playerInfos = infos });
  380. SendMatchList();
  381. }
  382. void OnServerCancelMatch(NetworkConnectionToClient conn)
  383. {
  384. if (!NetworkServer.active || !playerMatches.ContainsKey(conn)) return;
  385. conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Cancelled });
  386. Guid matchId;
  387. if (playerMatches.TryGetValue(conn, out matchId))
  388. {
  389. playerMatches.Remove(conn);
  390. openMatches.Remove(matchId);
  391. foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
  392. {
  393. PlayerInfo playerInfo = playerInfos[playerConn];
  394. playerInfo.ready = false;
  395. playerInfo.matchId = Guid.Empty;
  396. playerInfos[playerConn] = playerInfo;
  397. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
  398. }
  399. SendMatchList();
  400. }
  401. }
  402. void OnServerStartMatch(NetworkConnectionToClient conn)
  403. {
  404. if (!NetworkServer.active || !playerMatches.ContainsKey(conn)) return;
  405. Guid matchId;
  406. if (playerMatches.TryGetValue(conn, out matchId))
  407. {
  408. GameObject matchControllerObject = Instantiate(matchControllerPrefab);
  409. matchControllerObject.GetComponent<NetworkMatch>().matchId = matchId;
  410. NetworkServer.Spawn(matchControllerObject);
  411. MatchController matchController = matchControllerObject.GetComponent<MatchController>();
  412. foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
  413. {
  414. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Started });
  415. GameObject player = Instantiate(NetworkManager.singleton.playerPrefab);
  416. player.GetComponent<NetworkMatch>().matchId = matchId;
  417. NetworkServer.AddPlayerForConnection(playerConn, player);
  418. if (matchController.player1 == null)
  419. {
  420. matchController.player1 = playerConn.identity;
  421. }
  422. else
  423. {
  424. matchController.player2 = playerConn.identity;
  425. }
  426. /* Reset ready state for after the match. */
  427. PlayerInfo playerInfo = playerInfos[playerConn];
  428. playerInfo.ready = false;
  429. playerInfos[playerConn] = playerInfo;
  430. }
  431. matchController.startingPlayer = matchController.player1;
  432. matchController.currentPlayer = matchController.player1;
  433. playerMatches.Remove(conn);
  434. openMatches.Remove(matchId);
  435. matchConnections.Remove(matchId);
  436. SendMatchList();
  437. OnPlayerDisconnected += matchController.OnPlayerDisconnected;
  438. }
  439. }
  440. void OnServerJoinMatch(NetworkConnectionToClient conn, Guid matchId)
  441. {
  442. if (!NetworkServer.active || !matchConnections.ContainsKey(matchId) || !openMatches.ContainsKey(matchId)) return;
  443. MatchInfo matchInfo = openMatches[matchId];
  444. matchInfo.players++;
  445. openMatches[matchId] = matchInfo;
  446. matchConnections[matchId].Add(conn);
  447. PlayerInfo playerInfo = playerInfos[conn];
  448. playerInfo.ready = false;
  449. playerInfo.matchId = matchId;
  450. playerInfos[conn] = playerInfo;
  451. PlayerInfo[] infos = matchConnections[matchId].Select(playerConn => playerInfos[playerConn]).ToArray();
  452. SendMatchList();
  453. conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Joined, matchId = matchId, playerInfos = infos });
  454. foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
  455. {
  456. playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
  457. }
  458. }
  459. #endregion
  460. #region Client Match Message Handler
  461. void OnClientMatchMessage(ClientMatchMessage msg)
  462. {
  463. if (!NetworkClient.active) return;
  464. switch (msg.clientMatchOperation)
  465. {
  466. case ClientMatchOperation.None:
  467. {
  468. Debug.LogWarning("Missing ClientMatchOperation");
  469. break;
  470. }
  471. case ClientMatchOperation.List:
  472. {
  473. openMatches.Clear();
  474. foreach (MatchInfo matchInfo in msg.matchInfos)
  475. {
  476. openMatches.Add(matchInfo.matchId, matchInfo);
  477. }
  478. RefreshMatchList();
  479. break;
  480. }
  481. case ClientMatchOperation.Created:
  482. {
  483. localPlayerMatch = msg.matchId;
  484. ShowRoomView();
  485. roomGUI.RefreshRoomPlayers(msg.playerInfos);
  486. roomGUI.SetOwner(true);
  487. break;
  488. }
  489. case ClientMatchOperation.Cancelled:
  490. {
  491. localPlayerMatch = Guid.Empty;
  492. ShowLobbyView();
  493. break;
  494. }
  495. case ClientMatchOperation.Joined:
  496. {
  497. localJoinedMatch = msg.matchId;
  498. ShowRoomView();
  499. roomGUI.RefreshRoomPlayers(msg.playerInfos);
  500. roomGUI.SetOwner(false);
  501. break;
  502. }
  503. case ClientMatchOperation.Departed:
  504. {
  505. localJoinedMatch = Guid.Empty;
  506. ShowLobbyView();
  507. break;
  508. }
  509. case ClientMatchOperation.UpdateRoom:
  510. {
  511. roomGUI.RefreshRoomPlayers(msg.playerInfos);
  512. break;
  513. }
  514. case ClientMatchOperation.Started:
  515. {
  516. lobbyView.SetActive(false);
  517. roomView.SetActive(false);
  518. break;
  519. }
  520. }
  521. }
  522. void ShowLobbyView()
  523. {
  524. lobbyView.SetActive(true);
  525. roomView.SetActive(false);
  526. foreach (Transform child in matchList.transform)
  527. {
  528. if (child.gameObject.GetComponent<MatchGUI>().GetMatchId() == selectedMatch)
  529. {
  530. Toggle toggle = child.gameObject.GetComponent<Toggle>();
  531. toggle.isOn = true;
  532. //toggle.onValueChanged.Invoke(true);
  533. }
  534. }
  535. }
  536. void ShowRoomView()
  537. {
  538. lobbyView.SetActive(false);
  539. roomView.SetActive(true);
  540. }
  541. void RefreshMatchList()
  542. {
  543. foreach (Transform child in matchList.transform)
  544. {
  545. Destroy(child.gameObject);
  546. }
  547. joinButton.interactable = false;
  548. foreach (MatchInfo matchInfo in openMatches.Values)
  549. {
  550. GameObject newMatch = Instantiate(matchPrefab, Vector3.zero, Quaternion.identity);
  551. newMatch.transform.SetParent(matchList.transform, false);
  552. newMatch.GetComponent<MatchGUI>().SetMatchInfo(matchInfo);
  553. newMatch.GetComponent<Toggle>().group = toggleGroup;
  554. if (matchInfo.matchId == selectedMatch)
  555. {
  556. newMatch.GetComponent<Toggle>().isOn = true;
  557. }
  558. }
  559. }
  560. #endregion
  561. }
  562. }