Hello,
I am making a multiplayer game utilizing the new distributed authority topology. The key gameplay mechanics are in, and i am now wanting to introduce a lobby system where players can connect together and setup the game before it is played.
To do this, i am using the lobby service unity provides, however I am having trouble finding out what should be best practice when using it in combination with distributed authority.
I have got the lobby page setup and working in a scene where players connect to each other, once all players ready up it then loads into the game successfully.
The way i am doing this is by loading a new game scene where there is a function that runs that initializes the multiplayer session by calling:
_session = await MultiplayerService.Instance.CreateOrJoinSessionAsync(sessionName, options);
To my understanding, this function actually creates an entirely new lobby and connects the player calling it to it, making the previous lobby my players were in redundant.
Does this mean I should just not utilize the lobby system on it’s own if I am creating a distributed authority game and just call the above function to create my lobby? The only issue being that I can’t find a great way to retrieve the lobby information without querying the lobby service for it. Is there a way I can retrieve it from within the ISession that is returned from the above function? Or pehaphs i can initialize the game session with the current lobby i have created?
The main issue that this causes is when it comes to the ability to restart my game, as when i restart the game scene i can’t find a good way of initializing the scene if at the beginning i am creating the session as I receive either of the following errors with each workaround i try:
- Just restarting the scene => player is already a member of the lobby
- Removing the player from lobby, then restarting scene => in my game, 1 person has to load the scene before anyone else. Once they have loaded the scene, they notify everyone else and they all then load the scene. If I’m restarting the game, 1 person is removed from the lobby and loads the scene, however they won’t be able to start the game with await MultiplayerService.Instance.CreateOrJoinSessionAsync(sessionName, options); as a lobby with the same name already exists. I can think of ways around this via deleting the old lobby entirely, but then how would the first player to load the scene notify everyone else?
My main question is to find out if there are best practices for managing game sessions and lobbies when loading and restarting scenes, as I’m scratching my head coming up with solutions, all of which i don’t like.
I’ve actually looked into it a bit more and it seems as if using the lobby service independently of building and managing my game session adds a layer of unnecessary functionality.
After some rework, I’ve found that the ISession framework fits my needs perfectly and actually seems to have a much more simple and straightforward API to push/pull data from the session.
Revisiting this, it seems attempting to configure the ISession framework to handle a lobby system isn’t the best solution.
What I am now attempting to do is to have an initial “PlayerGroupLobby” which will manage player groups across multiple sessions of games.
The idea being that the main lobby retains the state of a singular or series of games, and whenever the game is started/restarted, 1 player will load the scene first and start a new distributed authority within that session, notify the lobby when it’s ready, then all other plays listen to that event and load the now setup network scene.
Hey @Wataghwan it was really helpful, thanks
Did you know how to set/change region when creating/joining a session in distributive authority?
1 Like
Hey @Freddy_08 no problem.
The approach i would take would be when a player creates a lobby, assign a “region” to it in the lobby data depending on where that request came from.
Then, when players are searching for games to play or you’re utilizing the matchmaking service, you can use the lobby query filters to query for a lobby which is in a region you’re after.
This might help => Is there Lobby region?
Also, from my understanding of what I’ve heard from the distributed authority’s demos, the server location running the DA session will shift to a localized area depending on the location of the players in the game. So while you’ll definitely want to account for region accessibility, it might not be as big a problem.
The distributed authority session will use quality of service logic (QoS) and be allocated in the region of the session host (whoever creates the session). The session options extension can also take a region parameter to override the region (see below snippet and regions here: Relay locations and regions), if for some reason you want that. Typically I’d recommend to let QoS do its job to ensure lower latency games especially because we reserve the right to add, remove, or change names of regions at any time. So hardcoding string values might lead to indeterminate behavior at some point in the future (thus the call to the Relay region endpoint to get latest).
/// <summary>
/// Configures a session to use the distributed authority networking.
/// </summary>
/// <remarks>
/// The region is optional and defaults to "us-central1". The list of regions can be obtained from the Relay
/// Allocations Service via <see cref="Unity.Services.Relay.IRelayService.ListRegionsAsync"/>. To determine the
/// lowest latency region, use <see cref="Unity.Services.Qos.IQosService.GetSortedRelayQosResultsAsync"/>.
/// </remarks>
/// <param name="options">The <see cref="SessionOptions"/> this extension method applies to.</param>
/// <param name="region">The Relay region where the Relay allocation used by Distributed Authority will
/// happen.</param>
/// <typeparam name="T">The options' type.</typeparam>
/// <returns>The <see cref="SessionOptions"/>.</returns>
public static T WithDistributedAuthorityNetwork<T>(this T options, string region = null)
where T : SessionOptions
{
return options.WithOption(new ConnectionOption(ConnectionInfo.BuildDistributedConnection(region)));
}
Thanks, @Wataghwan and @mcanfield_unity, for the quick reply!
I’m building the game on WebGL, and since QoS doesn’t support WebGL, I was thinking of letting players choose any region where they can get a good ping
There is one problem even though I’m specifying the region in method “WithDistributedAuthorityNetwork” for DA, it still keeps falling back to the default one.
Interesting. I haven’t seen that happen as of yet, but might very well be because of the WebGL use case you bring up. We’ll take a look there first and see if that can be reproduced and then consider how to resolve it. Will put in on the items board to be picked up, thanks for the report.
2 Likes