Multiple matches on one server (or dynamic teams?)

Hi Matchmakers,

First of all, I really appreciate all the efforts of bringing this feature to life, it can potentially save tons of working hours and headaches for so many developers.

So I spent some time playing with the Matchmaker solution this week using the “Matchplay” demo,
After few days of figuring out all the different flows and configurations, I believe I ended up not finding a solution to our use-case. Which I believe could be a very common use-case.

One instance of our servers, is capable of hosting more than just one match, actually, it’s capable of hosting hundreds of them.

The only hope we had is to use the “teams”+“backfill” feature to support that, so we tried to start with 1 team and hoped more teams would be added dynamically, unfortunately, we were wrong, once a match starts, the teams state do not change by definition.

Is there any way to achieve multiple matches on one server? or at-least “teams” that can be dynamically created/removed from a “match”? or are there any plans to support that in the future?
We tried “hacking” that through a backfill ticket with fake generated teams, but it didn’t seem to work.

tldr:

Without this feature, we cannot find the matchmaker service cost efficient enough for us unfortunately, which is sad, because it’s so close to be there and everything but that, seemed great.

Thanks a lot,

Rom

Hello! What if you treated each of your “matches” as a matchmaking team? You could configure a matchmaking rule set that specifies minimum 1 team and maximum x teams, each with 2 players. The matchmaker would try to fill out as many of these teams as possible and they would all end up on the same server. Your server logic could then run each “team” as a separate “match”. If backfill is enabled, more players could then be backfilled into this server, up to the max number of teams.

Hi, really appreciate your response, and thats exactly what i tried to do, but seems like new teams cannot be created after a match was started, even when i tried enable backfilling. They were created on a new server instead.
And even if the teams were created (they were not) there would be no way to get the new teams data from the server and know which players are related to them.

Please correct me if im wrong.

Are you approving the backfill ticket? The new players/teams added to the match would be available on the backfill approval response.

Yes I approve like that:

async Task BackfillLoop()
        {
            while (Backfilling)
            {
                if (m_LocalDataDirty)
                {
                    var updatedProps = m_LocalBackfillTicket.Properties.MatchProperties;
                    Debug.Log($"Updating backfill ticket : teams: {JsonUtility.ToJson(updatedProps.Teams.Where(t=>t.PlayerIds.Count>0).ToArray())} players: {JsonUtility.ToJson(updatedProps.Players)}");
                    await MatchmakerService.Instance.UpdateBackfillTicketAsync(m_LocalBackfillTicket.Id, m_LocalBackfillTicket);
                    m_LocalDataDirty = false;
                }
                else
                {
                    m_LocalBackfillTicket = await MatchmakerService.Instance.ApproveBackfillTicketAsync(m_LocalBackfillTicket.Id);
                }

                if (!NeedsPlayers())
                {
                    await StopBackfill();
                    break;
                }

                //Backfill Docs reccommend a once-per-second approval for backfill tickets
                await Task.Delay(k_TicketCheckMs);
            }
        }

And my rules json looks like that:

{
  "Name": "MatchAll",
  "MatchDefinition": {
    "Teams": [
      {
        "Name": "1v1",
        "TeamCount": {
          "Min": 1,
          "Max": 100
        },
        "PlayerCount": {
          "Min": 1,
          "Max": 2
        }
      }
    ],
    "MatchRules": []
  },
  "BackfillEnabled": true
}

Is it 100% sure new teams can be created after a match was started?
I did see new players joining the match to existing teams, but no new teams were created. they were created in a new match. maybe I did something wrong?

I even tried to create “fake teams” like that, to make the matchmaker think that I have some empty teams in my match hoping it will try to fill them, but it didn’t work as well:

The matchmaker should be prioritizing backfilling over creating new matches.

What is your NeedsPlayers() function doing? Is it possible backfilling is being stopped prematurely?

here’s the github fork I created from the “MatchPlay” demo (branch testChanges),
in attempt to make it support backfilling of new teams…
the specific part responsible for the backfilling is here (MatchplayBackfiller.cs)

I don’t see any reason for it not to work… (even when I tried to remove the fake teams part it didn’t work…)
if you can find anything I’m doing that seems wrong to you I would really appreciate that…

again, I’m quite sure that the problem is that new teams cannot be created with backfllling, since new players are created in the already existing teams, but not in new teams…

(Note that I have not actually tried to run this in the editor. Just looking at github.)

NeedsPlayers() will stop backfill if the number of players in the match is equal to or greater than m_MaxPlayers. I’ve traced this value back through these calls:

Could you try either adding number of players (in this case, 200) to defaultGameInfo.MaxUsers or simply hardcoding this number to m_MaxPlayers? I suspect it may be calling backfill approve once and then stopping, which may explain why you fill just one player to an existing team and then new teams are created as new matches.

If this still does not work, please give us some time to investigate further internally. Any ticketIds you can provide here would be very helpful.

Hi, I appreciate the efforts,
by this line : public int MaxUsers = 10;
m_MaxPlayers will always be set to 10,
and what happens for me with my rules is that:

  • 1 player creates 1 match of 1 team (which is fine)
  • 2nd player joins the match (which is fine)
  • 3rd player will not create a new team in this match, but will create a new match (which is not fine)

Any news on that problem?

Nope, still waiting for unity response on this :confused:
Hope they can provide a solution…

Probably I’ll solve it, I’ll let you know if I come up with an idea.

I think dynamic teams is a feature that is not supported ( its also not documented anywhere… )
but if you manage to make it work… would be amazing : )

Treating each team as a match should work. The tricky part is handling backfill I think. I did something to work with so I’ll test it and will let you know.

thanks orcunsari, although, as much as would like to believe it should work, unfortunately, I really don’t see a problem with the way I handled backfill…
I tried other ways as well, you can check my fork on github also and see that new teams are not being created after the match was started… this feature is not supported and not documented anywhere sadly…
and I really hope someone can prove otherwise…

Are you able to join already allocated server? or it allocates different server for each team? I set up everything for my game except backfill and I hope backfill to get it working soon.

As I explained earlier:

once the match started no new teams can be created in it. they are created in a new match.
and I will be very surprised if you get a different result.

My suggestion is to make sure your backfill manager is working properly. I personally have spent over 24 hours of time uploading new builds, debugging them and adjusting code just to get simple backfilling working. The example code either seems a bit buggy, or I implemented it incorrectly (though it was largely a copy paste job with not much chance to go wrong).

The example code:

  1. It pulls the remote state every 1 second unless the data is marked as dirty, in which case instead it updates the remote state. I found however that it would update the remote state with information that the player left the game, and then after re-syncing, the server would believe there was still a player. For whatever reason this would lead to constant errors about not being able to find an allocation even though there was a potential match available. I changed mine to ignore remote state and just update the matchmaker when players leave the match. I am not sure, however, if this kicks people out of the queue when a player leaves the game. From my testing, the answer to that seemed to be: no.
  2. If the first player added by the matchmaker never joins the match, the game server is left in a permanent state of thinking there is 1 player in the game. Options are: set a timeout on the player joining (I used 60 seconds) and clear them out if they haven’t joined by that time. For some reason, this ghost player seems to block further allocation to the server. However, I am using specific userId keys for each client, so it’s possible that only the specific client was getting blocked for this reason and I was too lazy to test whether another client could connect.
  3. Manually deallocate the server if players reach zero, by shutting down.
  4. Start the backfill manager again if the server is at capacity.

If your server is not communicating a backfill ticket correctly, nobody can ever join the existing server.

I have to say, the whole process has been VERY frustrating and there were many times I considered just abandoning Unity Matchmaker to try a competitor. Whether I continue to run into issues remains to be seen.

After spending a LOT of time dealing with this issue, I have found the problem, there is a race condition bug in the example matchmaker code (which is the code you pasted): Remote backfill bug by jackuoll · Pull Request #30 · Unity-Technologies/com.unity.services.samples.matchplay · GitHub

A couple of things: If a userId is on the backfill ticket for an existing server, they can never be assigned to that server again until they are cleared or the backfill ticket is deleted. The logic there doesn’t make sense to me because it seems like a player SHOULD be assigned back into a match that the matchmaker already believes they’re backfilling (or update the ticket accordingly). This will cause a single userId to eventually allocate every server if they consistently trigger the bug and play for long enough.

The example matchmaker code also does not handle the case where a player accepted a matchmaker ticket but never joined the game. In that case, the player will permanently remain on the backfill ticket and never be able to join the game. The server will also stay allocated for quite some time, even when the SQH reports there being zero players online. You’ll have to write code to handle these scenarios, too. Personally I went for a 60 second timeout on the player being added to the ticket, to removing them from the backfiller if they haven’t joined.

Also if you are just copy pasting the example code, be aware that they do not manage teams in their code, since their code only accounts for having a single team. You’ll need to make sure you are handling team removals correctly when a player leaves, otherwise the ticket will get into a bad state, leading to a bad request status code, causing a crash and killing your backfill.

The tl;dr is: make sure your backfill ticket is actually “heartbeating” and that the values on the ticket are staying sane to the reality of your server allocation.