ConnectToBestCloudServer() for Unity's Turnbased SDK

JohnTube
JohnTube ✭✭✭✭✭
I've been looking at the Region docs page and I like the option "a) let the game client ping the different Photon Cloud regions and pre-select the one with the best ping". Since I'm using the Turnbased SDK for Unity there is no equivalent for ConnectToBestCloudServer(string gameVersion), I'm trying to make my own method to accomplish the same purpose.

I want to know if my approach is correct. I'm making use of UnityEngine.Ping class (it requires IP addresses only as it does not resolve DNS FQDNs) and System.Linq's extension method Min() (I don't know if it is a wise idea since Mono is not Linq friendly). I'm also assuming the AvailableRegionsServers and AvailableRegions have "the same respective indexes for regions".
1. call loadBalancingAPI.ConnectToNameServer();
2. call loadBalancingAPI.OpGetRegions(); in OnStateChanged() with state == ClientState.ConnectedToNameServer
3. StartCoroutine("ConnectToBestServer") in OnOperationResponse with OpGetRegion with operationResponse.OperationCode == OperationCode.GetRegions and operationResponse.ReturnCode == 0
IEnumerator ConnectToBestServer() {
            int[] pingTimes = new int[loadBalancingAPI.AvailableRegionsServers.Length];
            for (int i = 0; i < loadBalancingAPI.AvailableRegionsServers.Length; i++) {
                Ping ping = new Ping((loadBalancingAPI.AvailableRegionsServers[i].Split(':'))[0]);
                while (!ping.isDone) {
                    yield return null;
                }
                pingTimes[i] = ping.time;
            }
            int min = Array.IndexOf(pingTimes, pingTimes.Min());
            ConnectToRegionMaster(loadBalancingAPI.AvailableRegions[min]);
        }

So what do you think ?

Comments

  • Sorry for the late reply. I had this topic open for a days now. I wasn't sure how much I should write.

    This is approximately what we do in PUN, too, so it's totally fine.
    Here are a few tips to refine this:
    The initial ping to some server is sometimes quite a bit longer than subsequent ones. You might want to ping several times. Use the sum of several iterations.
    In some cases, ping.isDone never happens, afaik. You should have a timeout.
    You might want to make this optional, except for the first time start. You can save the result in the prefs. This speeds up connection and users get to connect to "their" region.
    Ping is not working on all platforms due to Unity. Some consoles might not have it. We do have an alternative but need to expose it properly. That will use our own udp package for pinging. Look out for that in an update.

    If you worry about .Min(), just work around it.
  • JohnTube
    JohnTube ✭✭✭✭✭
    I've already tweeked the code since my last post here's the last version :
    IEnumerator BestServerCoroutine() {
            float minPingTime = float.MaxValue;
            int minPingIndex = 0;
            float pingTime;
            for (int i = 0; i < loadBalancingAPI.AvailableRegionsServers.Length; i++) {
                pingTime = 0f;
                Ping ping = new Ping((loadBalancingAPI.AvailableRegionsServers[i].Split(':'))[0]);
                while (!ping.isDone && pingTime < minPingTime) {
                    pingTime += Time.deltaTime;
                    yield return null;
                }
                if (pingTime < minPingTime) {
                    minPingTime = pingTime;
                    minPingIndex = i;
                }
            }
            loadBalancingAPI.ConnectToRegionMaster(loadBalancingAPI.AvailableRegions[minPingIndex]);
        }
    

    Thanks for the PlayerPrefs idea, I think it's good to save the preferred region once calculated it might save some tiny time on start up. But the problem is that in the game only players in the same region will be auto-matched ! and my game is a board/word game with multilanguages support so this might be as good as bad (especially for polyglots) ! also if a region is less "crowded" than other regions I might have bigger problems "load balancing" : meaning some players in a region might wait longer for an opponent even with LobbyType.AsyncRandomLobby while other regions are "full" of players and matchmaking is faster ! What do you think ? And I'm planning to implement friends invitations/challenges : can a player connected to a region join his friend's game created in another region ? will Photon automatically disconnect from the first region and reconnect to the other one ?
  • If the game doesn't need super fast ping, then you should definitely limit the number of regions used at the beginning to get more activity per region.
    Usually, the daily peak interest is at different times per region. In Asia, players will be sleeping when the US are most active. It should be OK to use a few regions but as said: If you don't need the speed, then use only a few.

    When you do invites, you will somehow need to know the region where the friend is playing. Photon has not built-in way to detect which region to use for a room name. Sorry but there is no switch to the correct region behind the scenes.