PhotonStatsGui.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <copyright file="PhotonStatsGui.cs" company="Exit Games GmbH">
  3. // Part of: Photon Unity Utilities,
  4. // </copyright>
  5. // <summary>
  6. // Basic GUI to show traffic and health statistics of the connection to Photon,
  7. // toggled by shift+tab.
  8. // Part of the [Optional GUI](@ref optionalGui).
  9. // </summary>
  10. // <author>developer@exitgames.com</author>
  11. // --------------------------------------------------------------------------------------------------------------------
  12. using UnityEngine;
  13. using Photon.Pun;
  14. using Photon.Realtime;
  15. using ExitGames.Client.Photon;
  16. namespace Photon.Pun.UtilityScripts
  17. {
  18. /// <summary>
  19. /// Basic GUI to show traffic and health statistics of the connection to Photon,
  20. /// toggled by shift+tab.
  21. /// </summary>
  22. /// <remarks>
  23. /// The shown health values can help identify problems with connection losses or performance.
  24. /// Example:
  25. /// If the time delta between two consecutive SendOutgoingCommands calls is a second or more,
  26. /// chances rise for a disconnect being caused by this (because acknowledgements to the server
  27. /// need to be sent in due time).
  28. /// </remarks>
  29. /// \ingroup optionalGui
  30. public class PhotonStatsGui : MonoBehaviour
  31. {
  32. /// <summary>Shows or hides GUI (does not affect if stats are collected).</summary>
  33. public bool statsWindowOn = true;
  34. /// <summary>Option to turn collecting stats on or off (used in Update()).</summary>
  35. public bool statsOn = true;
  36. /// <summary>Shows additional "health" values of connection.</summary>
  37. public bool healthStatsVisible;
  38. /// <summary>Shows additional "lower level" traffic stats.</summary>
  39. public bool trafficStatsOn;
  40. /// <summary>Show buttons to control stats and reset them.</summary>
  41. public bool buttonsOn;
  42. /// <summary>Positioning rect for window.</summary>
  43. public Rect statsRect = new Rect(0, 100, 200, 50);
  44. /// <summary>Unity GUI Window ID (must be unique or will cause issues).</summary>
  45. public int WindowId = 100;
  46. public void Start()
  47. {
  48. if (this.statsRect.x <= 0)
  49. {
  50. this.statsRect.x = Screen.width - this.statsRect.width;
  51. }
  52. }
  53. /// <summary>Checks for shift+tab input combination (to toggle statsOn).</summary>
  54. public void Update()
  55. {
  56. if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKey(KeyCode.LeftShift))
  57. {
  58. this.statsWindowOn = !this.statsWindowOn;
  59. this.statsOn = true; // enable stats when showing the window
  60. }
  61. }
  62. public void OnGUI()
  63. {
  64. if (PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsEnabled != statsOn)
  65. {
  66. PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsEnabled = this.statsOn;
  67. }
  68. if (!this.statsWindowOn)
  69. {
  70. return;
  71. }
  72. this.statsRect = GUILayout.Window(this.WindowId, this.statsRect, this.TrafficStatsWindow, "Messages (shift+tab)");
  73. }
  74. public void TrafficStatsWindow(int windowID)
  75. {
  76. bool statsToLog = false;
  77. TrafficStatsGameLevel gls = PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsGameLevel;
  78. long elapsedMs = PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsElapsedMs / 1000;
  79. if (elapsedMs == 0)
  80. {
  81. elapsedMs = 1;
  82. }
  83. GUILayout.BeginHorizontal();
  84. this.buttonsOn = GUILayout.Toggle(this.buttonsOn, "buttons");
  85. this.healthStatsVisible = GUILayout.Toggle(this.healthStatsVisible, "health");
  86. this.trafficStatsOn = GUILayout.Toggle(this.trafficStatsOn, "traffic");
  87. GUILayout.EndHorizontal();
  88. string total = string.Format("Out {0,4} | In {1,4} | Sum {2,4}", gls.TotalOutgoingMessageCount, gls.TotalIncomingMessageCount, gls.TotalMessageCount);
  89. string elapsedTime = string.Format("{0}sec average:", elapsedMs);
  90. string average = string.Format("Out {0,4} | In {1,4} | Sum {2,4}", gls.TotalOutgoingMessageCount / elapsedMs, gls.TotalIncomingMessageCount / elapsedMs, gls.TotalMessageCount / elapsedMs);
  91. GUILayout.Label(total);
  92. GUILayout.Label(elapsedTime);
  93. GUILayout.Label(average);
  94. if (this.buttonsOn)
  95. {
  96. GUILayout.BeginHorizontal();
  97. this.statsOn = GUILayout.Toggle(this.statsOn, "stats on");
  98. if (GUILayout.Button("Reset"))
  99. {
  100. PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsReset();
  101. PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsEnabled = true;
  102. }
  103. statsToLog = GUILayout.Button("To Log");
  104. GUILayout.EndHorizontal();
  105. }
  106. string trafficStatsIn = string.Empty;
  107. string trafficStatsOut = string.Empty;
  108. if (this.trafficStatsOn)
  109. {
  110. GUILayout.Box("Traffic Stats");
  111. trafficStatsIn = "Incoming: \n" + PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsIncoming.ToString();
  112. trafficStatsOut = "Outgoing: \n" + PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsOutgoing.ToString();
  113. GUILayout.Label(trafficStatsIn);
  114. GUILayout.Label(trafficStatsOut);
  115. }
  116. string healthStats = string.Empty;
  117. if (this.healthStatsVisible)
  118. {
  119. GUILayout.Box("Health Stats");
  120. healthStats = string.Format(
  121. "ping: {6}[+/-{7}]ms resent:{8} \n\nmax ms between\nsend: {0,4} \ndispatch: {1,4} \n\nlongest dispatch for: \nev({3}):{2,3}ms \nop({5}):{4,3}ms",
  122. gls.LongestDeltaBetweenSending,
  123. gls.LongestDeltaBetweenDispatching,
  124. gls.LongestEventCallback,
  125. gls.LongestEventCallbackCode,
  126. gls.LongestOpResponseCallback,
  127. gls.LongestOpResponseCallbackOpCode,
  128. PhotonNetwork.NetworkingClient.LoadBalancingPeer.RoundTripTime,
  129. PhotonNetwork.NetworkingClient.LoadBalancingPeer.RoundTripTimeVariance,
  130. PhotonNetwork.NetworkingClient.LoadBalancingPeer.ResentReliableCommands);
  131. GUILayout.Label(healthStats);
  132. }
  133. if (statsToLog)
  134. {
  135. string complete = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}", total, elapsedTime, average, trafficStatsIn, trafficStatsOut, healthStats);
  136. Debug.Log(complete);
  137. }
  138. // if anything was clicked, the height of this window is likely changed. reduce it to be layouted again next frame
  139. if (GUI.changed)
  140. {
  141. this.statsRect.height = 100;
  142. }
  143. GUI.DragWindow();
  144. }
  145. }
  146. }