How to fix matchmaking when only a few users are existing?

Hi Photon Community!

In my project, matchmaking works in a way now is that it search for available rooms and checks if there's any user in them. And if not, then it starts a room itself and wait for users to join.

It works perfectly when one of the users waits until it has created its room, and when it starts to joining, it finds the room and joins. No waiting would be needed if there would be more rooms to join, so there would be 5-10 users.

But the problem is for example when there're only two players, and the two players start the matchmaking at the same time, there's a chance that they can't find each other. They both try to find a different room, and they both create a room on their own.

What is the best practice of solving this? Creating room and waiting first, and joining to a different room after a few seconds?

Comments

  • Maybe the problem could be solved only if a user could be on Game server (to be in a room waiting for others to join) and on the Master server (to do matchmaking and check all the different rooms)? Is it possible to be on those two servers at the same time?
    Or am I missing something?
  • Kaiserludi
    Kaiserludi admin
    edited June 2021
    Hi @gregtom6.

    Just use opJoinOrCreateRoom() or opJoinRandomOrCreateRoom(). That's exactly what those operations are there for.
    When your two users both do that at the same time, the user whose request arrives at the server first, will create a new room and the other user will join that room.
  • @Kaiserludi and how to use this exactly? Because as I can see, PhotonNetwork doesn't have any static methods like this, and loadBalancingClient.OpJoinRandomOrCreateRoom(...) seems to be an inner method, which is not meant to be used outside I think (at least I could avoid to use any methods of that until now, and I used everything from PhotonNetwork)
  • The problem you want to solve is really rare. If a game has next to no players, it's unlikely 2 will decide to play at the same time, so close to one another that they don't match.
    This is usually just a development-time issue, where you start multiple clients to test.
    That said: I agree it's annoying.

    Actually, we did not implement OpJoinRandomOrCreateRoom in PUN 2.
    This is something we can add.

    I think this should work, if added to the PhotonNetwork class:
    public static bool JoinRandomOrCreateRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter, string roomName, RoomOptions roomOptions = null, string[] expectedUsers = null)
    {
        if (OfflineMode)
        {
            if (offlineModeRoom != null)
            {
                Debug.LogError("JoinRandomOrCreateRoom failed. In offline mode you still have to leave a room to enter another.");
                return false;
            }
            EnterOfflineRoom("offline room", null, true);
            return true;
        }
        if (NetworkingClient.Server != ServerConnection.MasterServer || !IsConnectedAndReady)
        {
            Debug.LogError("JoinRandomOrCreateRoom failed. Client is on "+ NetworkingClient.Server+ " (must be Master Server for matchmaking)" + (IsConnectedAndReady ? " and ready" : " but not ready for operations (State: "+ NetworkingClient.State + ")") + ". Wait for callback: OnJoinedLobby or OnConnectedToMaster.");
            return false;
        }
    
        typedLobby = typedLobby ?? ((NetworkingClient.InLobby) ? NetworkingClient.CurrentLobby : null); // use given lobby, or active lobby (if any active) or none
    
        OpJoinRandomRoomParams opParams = new OpJoinRandomRoomParams();
        opParams.ExpectedCustomRoomProperties = expectedCustomRoomProperties;
        opParams.ExpectedMaxPlayers = expectedMaxPlayers;
        opParams.MatchingType = matchingType;
        opParams.TypedLobby = typedLobby;
        opParams.SqlLobbyFilter = sqlLobbyFilter;
        opParams.ExpectedUsers = expectedUsers;
    
        EnterRoomParams enterRoomParams = new EnterRoomParams();
        enterRoomParams.RoomName = roomName;
        enterRoomParams.RoomOptions = roomOptions;
        enterRoomParams.Lobby = typedLobby;
        enterRoomParams.ExpectedUsers = expectedUsers;
    
        return NetworkingClient.OpJoinRandomOrCreateRoom(opParams, enterRoomParams);
    }
    


    We can add this in PUN 2.33 or up, I guess.
  • @Tobias We have made a discussion in the Discord channel about that this is not working for both of us after testing, only room creation is happening for both users, but they doesn't join to each other.
    As you asked, I'm sending an email to developer@photonengine.com as a reminder.
  • We'll look into this early next week but I can't say when this gets fixed. Depends on what the issue is.
    Thx for the mail. I'll use that to ping you.
  • JohnTube
    JohnTube ✭✭✭✭✭
    Hey, late comment but wanted to mention that, although PhotonNetwork.JoinRandomOrCreateRoom does not exist, we show you how you can use JoinRandomOrCreateRoom from PUN here.
  • I tested some more and now see it should work. Important: The max players value for the random matchmaking should be 0 or match the actual max players value used in the created room(s). Then matchmaking will find or create the room (as far as I can see).

    @gregtom6, let us know if this is not the case.
  • gregtom6
    gregtom6
    edited July 2021
    @Tobias I didn't try to solve this since June, I had other tasks.

    I downloaded the newest Photon Pun 2 version, but it still doesn't work. I have tried the parameters suggested by tagergo in Discord back at June 11 (changing roomName to null instead of "", changing matchingType to MatchmakingMode.FillRoom, using sqlLobbyFilter as null instead of "", using TypedLobby.Default for typedLobby)
    I even tried using PhotonNetwork.JoinRandomOrCreateRoom without any parameters, still no success.

    These are the commands I'm using in this order:
    PhotonNetwork.NickName="test";
    PhotonNetwork.GameVersion = Application.version;
    
    PhotonNetwork.NetworkingClient.AppId = PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime;
    
    PhotonNetwork.ConnectUsingSettings();
    

    then the OnConnectedToMaster method gets running, inside that I call:
    PhotonNetwork.OnPlayerEnteredRoom();
    

    then the OnJoinedRoom is running, but the PhotonNetwork.CurrentRoom.PlayerCount will never gets greater than 1.

    OnPlayerEnteredRoom method never runs with JoinRandomOrCreateRoom.
  • gregtom6
    gregtom6
    edited July 2021
    @Tobias I realized the problem was occured, because parallel to JoinRandomOrCreateRoom, I was also overriding OnRegionListReceived, and I called PhotonNetwork.ConnectToRegion too. So it works now in my local region.

    Now my problem is that previously I used PhotonNetwork.ConnectToRegion, as I remember correctly (I can checkout to previous commit if needed), the OnJoinRandomFailed was running if no users were found in a certain region, and I could join to the next region with the next lowest ping.

    But JoinRandomOrCreateRoom method doesn't return to OnJoinRandomFailed. So if I want to achieve a global matchmaking now, should I connect to the lowest pinged region, and if client can't connect to any other users in a certain time or no one is joining to him during this time, then I disconnect and connect to the other region? Unfortunately in this case I would miss users in lower pinged regions if my client is in an another region and it's waiting for an another user to join.

    Isn't there a solution, which parallelly checks every region and if there is a user in a region, then it joins to him? Or if there are multiple users in lower and higher pinged regions too, then client connects to the lowest pinged region user?
  • If you have almost no players, they need to meet in one region or won't find one another (if everyone jumps regions but never waits to be found, our matchmaking doesn't work well).
    You can use one or very few regions to get matches done until more players play and then you open up new regions. This is far easier than coming up with a scheme in which clients hop around regions, etc.

    One refinement: Each client could detect it's best region, then still connect to the "global" region for matchmaking. When players are in a room, you could sync their best regions. Have everyone agree on a better region, disconnect and JoinOrCreate the same room in that other region.

    Better put more work in the game and make sure many players will play it :)
  • Hi team,

    I am using Photon-Javascript_SDK.js (libversion=4.1.0.0), and I have the same issue. Two users might decide to create two different rooms, any solid fix for this, please.

  • Tobias
    Tobias admin
    edited December 2021

    Please call joinRoom() with 'createIfNotExists' option: https://doc-api.photonengine.com/en/javascript/current/Photon.LoadBalancing.LoadBalancingClient.html#joinRoom

    You can find an example of such call in demo-loadbalancing.

    This will avoid most misses: If a client doesn't find a room, the very same operation will create one instantly, which can be found by the next client's operation.

  • Hi Tobias,

    Thanks for your reply.  joinRoom() with 'createIfNotExists' solves the issue for predefined room names (which I don't know). [it does not accept null/empty names]

    In my case I need the player to join any available random room, if not found create the room (with no names, so Photon will assign the name randomly).

    I ended up doing the workaround as follows:

    1] Join a random room

    2] If not found, create one

    3] Wait for a random delay, if no user joined, then leave the room and restart the process (from (1))

    Do you think there is a better solution, or is there any JS implementation for (JoinRandomOrCreateRoom)?

    Thanks,

  • JohnTube
    JohnTube ✭✭✭✭✭

    Hey @tnageleweb,

    Thank you for choosing Photon!

    I invite you and @Tobias to continue the discussion on the other thread here.