How to set up player roles in anon/relay matchmaking

Our basic scenario:

Two-player game, Unity client, relay server, using anonymous authentication.

We already have random matchmaking working with random role assignment as well as pre-arranged matches between two players with assigned roles (Red vs Blue). None of this so far requires changes to the server. Everything can be handled on the client side.

We want to update our code to handle adding an Observer role to a match. As the name implies, they can watch a game, but they don’t participate. They are also not required for a game to start and can be late-join, popping in and out if needed.

So for both match scenarios we would like to have a means of identifying the user joining a match by some kind of role identifier. Basically we want to ensure that game won’t start until both active players are present. So in random matchmaking this would work something like:

mmTicket = await _connectionManager.MainSocket.AddMatchmakerAsync(“*”, 2, 3);

But we won’t receive a signal on socket.ReceivedMatchmakerMatched unless two active players have been matched. 1 active + 1 observer would wait for a second active player and ultimately timeout if one didn’t show up.

What sort of methods are available on the server side (we’d write any extension code in Go) to facilitate this?

Thanks!

-A

Hi @AllenPDX,

Adding a property such as “observer”:true/false, and have the match query be something like:

("properties.observer:F", 2,3) (boolean values must be queried with T/F).

and have each player registering into the matchmaker pool by setting the property accordingly.

Notice that the properties.observer:false query property is not prefixed with a +, meaning it’ll prefer matches that comply but not strictly enforce it. However, this won’t guarantee you can’t get matches with 2+ observers, in such case the client should inspect whether the matches are suitable, and if not, automatically go back into the pool. You can use boosting to give further preference for non-observers to match.

Complementary to this, and to allow an Observer to join an ongoing match, you can use Storage Search: the host of a successfully created match would call a custom RPC periodically as an heartbeat for ongoing matches and set an expiry time in the future. The value will depend on match length and heartbeat periodicity. You’d then use the Storage Search listing operation with a filter to find matches that are still ongoing (expiry in the future), and are not completed (another RPC the host could call on match end) and join as an observer.

I think it’s a good idea to drop Observers out of the pool and use the above to look for any ongoing matches if they can’t find a match via the matchmaker after a while.

You’d also need a background worker to periodically delete these objects for matches that have completed or have an expiry time in the past. You can achieve this either via a background goroutine or a custom Server-to-Server RPC that is called via a CRON job.

Hope this helps.

Thanks for the pointers! I had forgotten about using queries. Definitely can be used as a part of our strategy.