Search Unity

Acquiring Servers Ping

Discussion in 'Multiplayer' started by oakshiro, Dec 18, 2008.

  1. oakshiro

    oakshiro

    Joined:
    Dec 9, 2008
    Posts:
    20
    Hi there,

    We have been testing some MasterServer implementation on my local network.
    We have configured a MasterServer, and created some Hosts.
    We have successfully received the server list using the MasterServer.PollHostList method and so on...

    The problem is we want the client to connect automatically to the best suitable server, taking into account the server load (users connected and ping), and we are unable to get the ping value correctly.

    If we use this piece of code:
    Code (csharp):
    1.  
    2. var ServerPing : Ping;
    3.  
    4. function OnGUI()
    5. {
    6.   ServerPing = Ping("192.168.1.59");
    7.   while(!ServerPing.isDone) {}
    8.   var Latency : String = (ServerPing.time).ToString();
    9.   guiText.text = ("Server latency: " + Latency);
    10. }
    11.  
    Unity almost freezes on mac, and totally freezes or even do not load on windows.

    On the other hand, trying to do something similar to this (deleted other code to go straight to the bone):

    Code (csharp):
    1.  
    2. var ServerPing : Ping;
    3. var PingTime = -2;
    4.  
    5. function Awake()
    6. {
    7.  ServerPing = Ping("192.168.1.59");
    8. }
    9.  
    10. function OnGUI()
    11. {
    12.   if (PingTime < -2)
    13. {
    14.   var Latency : String = (ServerPing.time).ToString();
    15.   guiText.text = ("Server latency: " + Latency);
    16. }
    17. }
    18.  
    19. function Update()
    20. {
    21.   if(ServerPing.isDone)
    22.     PingTime = ServerPing.time;
    23. }
    24.  
    But it seems that ServerPing is not accessible from Update...

    I don't know, I think this should be easier than it seems. Am I doing something terribly wrong? I have been searching throughout all the forum with no success...

    Thanks in advance[/code]
     
  2. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    This "while(!ServerPing.isDone) {}" is really not a good idea because it will stop Unity while it's trying to execute OnGUI. What you should do instead is start somewhare (e.g. in the in GUI) and then in each call to OnGUI check if ServerPing.isDone. Obviously you can't start Ping(...) each time OnGUI is called so one option is using a flag and once this is set, you don't call Ping(...) anymore - but instead check for ServerPing.isDone and when that's the case, calculate your latency.

    Sunny regards,
    Jashan
     
  3. oakshiro

    oakshiro

    Joined:
    Dec 9, 2008
    Posts:
    20
    Hi Jashan,

    Thanks for answering.

    Actually, our second way to do it was exactly as you say, but it seems there is something wrong with our code.

    This code now works as intended, It shows a list of all the registered servers and their pings when available, but only stores a single Ping value:

    Code (csharp):
    1.  
    2. var ServerPing: Ping;
    3. var NumServers : int = 0;
    4. var bAllServersPinged : boolean = false;
    5. var hostData : HostData[];
    6. var firstLaunch = true;
    7.  
    8. function Awake() {
    9.     MasterServer.ipAddress = "192.168.1.32";
    10.     MasterServer.port = 25000;
    11.     MasterServer.ClearHostList();
    12.     MasterServer.RequestHostList("EnneGame");
    13.     hostData = MasterServer.PollHostList();
    14.  
    15. }
    16.  
    17. function InitializePings()
    18. {  
    19.    
    20.     hostData = MasterServer.PollHostList();
    21.     if (hostData.length != 0)
    22.     {
    23.         for(var i=0;i<hostData.length;i++)
    24.         {
    25.             ServerPing=new Ping("192.168.1.104");
    26.         }
    27.         NumServers = 1;
    28.     }
    29.     else
    30.     {
    31.         guiText.text=("no server found");
    32.     }  
    33. }
    34.  
    35. function OnGUI() {
    36.         if (Network.peerType == NetworkPeerType.Disconnected)
    37.         {
    38.             guiText.text = ("");
    39.            
    40.             if (hostData.length != 0)
    41.             {
    42.    
    43.                 guiText.text = ("Available servers...");
    44.                
    45.                 GUI.Box(Rect(10,40, (Screen.width-20), (Screen.height-80)),"");
    46.                 GUILayout.BeginArea(Rect(20,50, (Screen.width-40), (Screen.height-100)));
    47.                                        
    48.                 for (var i = 0; i<hostData.length; i++)
    49.                 {                      
    50.                     GUILayout.BeginHorizontal();
    51.                     var name = hostData[i].gameName + " " + hostData[i].connectedPlayers + " / " + hostData[i].playerLimit;
    52.                     GUILayout.Label(name); 
    53.                     GUILayout.Space(5);
    54.                     var hostInfo;
    55.                     hostInfo = "[";
    56.                     for (var host in hostData[i].ip)
    57.                         hostInfo = hostInfo + host + ":" + hostData[i].port + " ";
    58.                     hostInfo = hostInfo + "]";
    59.                     GUILayout.Label(hostInfo); 
    60.                     GUILayout.Space(5);
    61.                     GUILayout.Label(hostData[i].comment);
    62.                    
    63.                     if(ServerPing.isDone)
    64.                     {
    65.                         var Latency : String = (ServerPing.time).ToString();           
    66.                         GUILayout.Space(5);
    67.                         GUILayout.Label( "(" + Latency + " ms)");
    68.                     }
    69.                     else
    70.                     {
    71.                         GUILayout.Space(5);
    72.                         GUILayout.Label( "(pinging...)");
    73.                     }
    74.                    
    75.                     GUILayout.Space(5);
    76.                     GUILayout.FlexibleSpace();
    77.                     GUILayout.EndHorizontal();
    78.                 }          
    79.                                    
    80.                 GUILayout.EndArea();
    81.             }
    82.             else
    83.             {
    84.                 guiText.text = ("Server list empty, hit refresh to fetch new list");
    85.             }
    86.            
    87.             if (GUILayout.Button("Refresh server list"))
    88.             {
    89.                 MasterServer.RequestHostList("EnneGame");
    90.                 InitializePings();
    91.             }
    92.    
    93.         }
    94.         else
    95.         {
    96.             guiText.text = ("Connected to: " + BestServerIp);
    97.            
    98.             if (GUILayout.Button ("Disconnect"))
    99.             {
    100.                 Network.Disconnect(200);
    101.             }
    102.         }
    103. }
    104.  
    105. function OnConnectedToServer() {
    106.     // Notify our objects that the level and the network is ready
    107.     for (var go in FindObjectsOfType(GameObject))
    108.         go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);    
    109. }
    110.  
    111. function OnDisconnectedFromServer () {
    112.     if (this.enabled != false)
    113.         Application.LoadLevel(Application.loadedLevel);
    114.     else
    115.         FindObjectOfType(NetworkLevelLoad).OnDisconnectedFromServer();
    116. }
    117.  
    118. function Update(){
    119.    
    120.     if(firstLaunch)
    121.     {
    122.         InitializePings();
    123.         firstLaunch = false;
    124.     }  
    125.    
    126. }  
    127.  
    This works fine.
    The problem is, if we now change...

    Code (csharp):
    1. var ServerPing: Ping;
    for...

    Code (csharp):
    1. var ServerPing: Ping[];
    And all the calls that were something like...
    Code (csharp):
    1. if(ServerPing.isDone)
    2. {
    3.   var Latency : String = (ServerPing.time).ToString();         
    4.                         GUILayout.Space(5);
    5.                         GUILayout.Label( "(" + Latency + " ms)");
    6.                     }
    for...
    Code (csharp):
    1. if(ServerPing[0].isDone)
    2. {
    3.   var Latency : String = (ServerPing[0].time).ToString();          
    4.                         GUILayout.Space(5);
    5.                         GUILayout.Label( "(" + Latency + " ms)");
    6.                     }
    ... it comes up with a NullReferenceException error, and i don't understand why...
    May it be possible that, when we perform a PollHostList we could be losing all references that were inside the Ping array?..

    I am completely stuck here, and can't understand why a single variable works and an array don't...

    thanks in advance
     
  4. oakshiro

    oakshiro

    Joined:
    Dec 9, 2008
    Posts:
    20
    Ok!, I found the solution myself.
    I needed to specify a length for the ServerPing array! how dumb!...

    I simply added this just before filling the ping values and it worked!

    Code (csharp):
    1. ServerPing = new Ping[hostData.length];

    Thanks for your kind help!
     
  5. xuanthonb

    xuanthonb

    Joined:
    Jan 19, 2017
    Posts:
    1
    Ping not return when Sever Die.