This document is about: FUSION 2
SWITCH TO

Matchmaking API

Introduction

One key requirement while creating a multiplayer game is to easily be able to match players together with similar skills, level, or who want to play the same game type or map, making the overall experience in-game as enjoyable as possible. For this purpose, Photon Fusion exposes a set of API calls that can be used to create the best experience for players looking for the perfect match.

Photon Fusion works with the Photon Cloud transparently, so most of the interactions with the Photon backend services are done automatically. This page describes the Fusion Matchmaking API, which is used to create a Game Session optionally with custom properties that can be used by players to filter/join the best Session based on their desired gameplay experience.

Glossary

In order to fully understand the API, below are described some terms used along this document that are directly related to the correct usage of the Matchmaking API.

  • Game Session: Or just Session, is where Players meet to play a match or communicate. This is what gets published in the Photon Cloud and is made available so other clients can search, filter, and join a particular game. Communication outside of any Session is not possible and any client can only be active in one Session. Game Sessions have the following characteristics: they can be created and joined by name, have Custom Properties, a maximum player count, can be hidden (not shown in a Lobby) or visible, and can be closed (no one can join) or open. In PUN and Photon Realtime, it is called a Room.
  • Lobby: Is a virtual container or "list" of Sessions. It is possible to use multiple lobbies to split the sessions between different game types, for example, as it is basically a way to have a Game Session listed within an arbitrary set of sessions. Clients can't communicate in the Lobby and they never know that another client is also in the lobby.

A client can only be in a Lobby, a Game Session or neither.

Creating and Joining a Game Session

The Game Session creation and joining are two parts of the same procedure, and the rules are simple:

  1. If there is no Session with the specified SessionName, a new one will be created (not in all cases as explained below) with that SessionName.
  2. If there is already a Session with that SessionName, the peer will join it. A Server or Host cannot join a Session that already has a Server or Host.

In terms of API, all of this is done automatically when a new Fusion Simulation is started. Below are the main arguments that can be used to customize the Session when creating a new one or used as a filter when looking for a Session to join:

C#

runner.StartGame(new StartGameArgs {
  // ...
  // Arguments related to the Matchmaking between peers
  SessionName = [string],
  SessionProperties = [Dictionary<string, SessionProperty>],
  CustomLobbyName = [string],
  EnableClientSessionCreation = [bool?],
  PlayerCount = [int?],
  IsOpen = [bool?],
  IsVisible = [bool?],
  MatchmakingMode = [MatchmakingMode?],
});

All the matchmaking related arguments are optional. Each description includes the value Fusion uses when the argument is not set:

Argument Description
SessionName The Game Session's Name or ID, it identifies the session on the Photon Cloud and it must be unique within a Region. Defaults to the name returned by StartGameArgs.SessionNameGenerator, or else a random GUID.
SessionProperties The Session's Custom Properties are a way to include metadata on your Game Session, like the game mode/type or the current map, for example. Keep in mind that all properties are always published to the Lobby when creating the Session and those properties can be used as matching filters when a peer is joining a random Session (read more below). As a suggestion, always try to keep the Property Keys as short as possible in order to minimize traffic. Defaults to empty.
CustomLobbyName Sets a custom Lobby Name with which the Session will be associated. Defaults to the ClientServer Lobby in Host, Server, Client and AutoHostOrClient, and the Shared Lobby in Shared. See Lobbies and Matchmaking for more info.
EnableClientSessionCreation Changes which Client peer types can create a new Game Session or only join one. Defaults to false in Client, and true in Shared and AutoHostOrClient. See below for more info.
PlayerCount Defines the maximum number of peers in a Session, including the Host. In Server mode, one extra slot is added for the dedicated Server. This parameter is only used when creating a new Session. Defaults to Simulation.PlayerCount of StartGameArgs.Config when set, or else of NetworkProjectConfig.Global.
IsOpen Defines if the Game Session being created (when applicable), will be set as open for any other players to join. Defaults to true. See Changing the Session for more info.
IsVisible Defines if the Game Session being created (when applicable), will be visible to other players. Defaults to true. See Changing the Session for more info.
MatchmakingMode Defines the matchmaking mode used when trying to join a Random Game Session. Defaults to FillRoom. See the values below.

MatchmakingMode values:

Value Description
FillRoom Fills up rooms (oldest first) to get players together as fast as possible. Default.
SerialMatching Distributes players across available rooms sequentially but takes filters into account. Without filter, rooms get players evenly distributed.
RandomMatching Joins a (fully) random room. Expected properties must match, but aside from this, any available room might be selected.

It is possible to create and join a Game Session, either at random or with a specific SessionName (useful for Game Invites, for example), and also enable Session filtering using custom properties, in order to only join games with specific configurations. This already provides a lot of flexibility when managing the sessions.

The following tables summarize how Fusion handles the Game Session creation and joining, which depends on the SessionName, GameMode, and whether EnableClientSessionCreation is enabled or not when starting the simulation.

In these tables, a valid SessionName is neither null nor empty. Fusion trims the name first, so a name made only of whitespace counts as empty.

Server and Host

EnableClientSessionCreation does not apply.

Session Name Result
Valid Create or Join Session
Empty/Null Create or Join Session with a generated name (SessionNameGenerator, else a random GUID)

Client

EnableClientSessionCreation Valid Empty/Null
null (default = false) Join Session Join Random Session
true Create or Join Session Join Random or Create
false Join Session Join Random Session

Shared and AutoHostOrClient

EnableClientSessionCreation Valid Empty/Null
null (default = true) Create or Join Session Join Random or Create
true Create or Join Session Join Random or Create
false Join Session Join Random Session

Getting and Updating the Game Session information

The NetworkRunner exposes the Game Session and the Lobby the local peer is in through NetworkRunner.SessionInfo and NetworkRunner.LobbyInfo, along with other Photon Cloud related properties.

Session Info

SessionInfo describes a Session, the Photon Cloud Room that hosts a Fusion game. It holds the Room's name, Region, player counts, open and visible flags, and the custom Session Properties. The Server, the Host or the Shared Mode Master Client can also use it to change the open and visible flags and the Session Properties.

Where To Read Session Info

API Description
NetworkRunner.SessionInfo Session the local peer is in. Never null. Valid from the moment StartGame has entered the Room, before the game starts. Replaced by a new, invalid record when StartGame or JoinSessionLobby connects to the Photon Cloud, and on Shutdown after the OnShutdown callbacks have run. In GameMode.Single, StartGame replaces it with a valid record when it completes (see Single Player Mode). Available on every peer.
OnSessionListUpdated(NetworkRunner, List<SessionInfo>) Sessions listed in the Lobby the peer joined with JoinSessionLobby (see Session List and Lobby Info). Available on peers in a Lobby.

Session Info Members

Member Description
IsValid True when the record holds the Room's data. False before the peer enters a Session, after the runner shuts down, and from the moment the local peer requests a change until the Photon Cloud confirms it (see Changing the Session). Type bool.
Name Room name. It is StartGameArgs.SessionName when set. Otherwise, it is the name of the Room found by a random join, or, when this peer creates the Room, the result of StartGameArgs.SessionNameGenerator, else a random GUID. Type string.
Region Photon Cloud Region the local peer is connected to. Type string.
IsOpen Whether new players can join the Session. Settable. Type bool.
IsVisible Whether the Session is listed in its Lobby. Settable. Type bool.
Properties Custom Session Properties (see Session Properties). Null until the record is first filled in. Type ReadOnlyDictionary<string, SessionProperty>.
PlayerCount Number of peers in the Room, including the Server or Host. Type int.
MaxPlayers Number of peers the Room accepts, set by the peer that created it: StartGameArgs.PlayerCount, or NetworkProjectConfig.Simulation.PlayerCount when not set. In Server mode, one extra slot is added for the dedicated Server. Type int.

SessionInfo converts implicitly to bool, which is true when the record is not null and IsValid is true. SessionInfo.ToString() returns every member on one line, ready for logging.

Session Properties

A SessionProperty holds an int, a string or a bool. It converts implicitly from and to these types, and converting to the wrong type throws InvalidCastException. IsInt, IsString and IsBool tell which type it holds.

Limit Value
Number of properties 10
Serialized size of all properties 500 bytes

StartGameArgs.SessionProperties has two roles:

  • When the peer creates the Session, they are its initial properties, and all of them are listed in the Lobby.
  • When the peer joins a random Session, only Sessions with matching values are joined.

StartGame fails with ShutdownReason.InvalidArguments if StartGameArgs.SessionProperties goes over either limit, in every Game Mode except GameMode.Single.

Keep in mind that the Session information and especially the Custom Properties, should be used for Matchmaking purposes only and never to synchronize game state information with the game clients, for example. We highly discourage such uses. If you need to exchange information session-wide that is related to gameplay, Fusion offers plenty of options, like having global NetworkObject instances or using RPCs for one-shot data.

Changing the Session

Only the Server or Host, or the Shared Mode Master Client, can change the Session. On every other peer, setting IsOpen or IsVisible is ignored and UpdateCustomProperties returns false.

API Effect
IsOpen = value Opens or closes the Session to new players.
IsVisible = value Lists the Session in its Lobby, or hides it.
UpdateCustomProperties(Dictionary<string, SessionProperty>) Changes the values of existing properties. Keys the Session does not have yet are ignored, with a warning. Returns true if the request was sent, which needs at least one changed value. Returns false, with a warning, if the result goes over a limit.

A sent request sets IsValid to false until the Photon Cloud confirms the change. Until then, the members keep their previous values. The confirmation refreshes the record on every peer in the Session, including the one that sent the request, and sets IsValid back to true.

Setting IsOpen or IsVisible to its current value sends nothing and leaves IsValid unchanged.

Session List

OnSessionListUpdated is part of the INetworkRunnerCallbacks interface. The NetworkRunner registers the enabled components on its GameObject and children that implement it, and any other instance is registered with NetworkRunner.AddCallbacks (see Custom INetworkRunnerCallbacks).

OnSessionListUpdated is called while the peer is in a Lobby:

  • Each call passes every Session currently listed in the Lobby, not only the ones that changed.
  • A Session leaves the list when it becomes full, closed or invisible, or when it is removed.
  • The same SessionInfo instance is kept for a Session across calls and updated in place.
  • Region is the Region of the local peer.
  • The records are read-only: setting IsOpen or IsVisible is ignored and UpdateCustomProperties returns false.

Single Player Mode

In GameMode.Single there is no Room, and NetworkRunner.SessionInfo is a local record:

  • IsValid is true from the moment StartGame completes.
  • Name and Region are null, PlayerCount and MaxPlayers are 0.
  • IsOpen and IsVisible start as false, and setting them only changes the local value.
  • UpdateCustomProperties merges the given properties into Properties, with any key and without limits. StartGameArgs.SessionProperties is applied this way when StartGame completes.

Notes

  • NetworkRunner.SessionInfo is replaced on StartGame, JoinSessionLobby and Shutdown. Read it from the runner instead of keeping a reference.
  • There is no callback for changes to the current Session. Read NetworkRunner.SessionInfo when the data is needed.
  • if (runner.SessionInfo) checks for null and IsValid at once.

Examples

Closing a Session when the match starts

C#

// Server, Host or Shared Mode Master Client
void StartMatch(NetworkRunner runner) {
  runner.SessionInfo.IsOpen    = false;
  runner.SessionInfo.IsVisible = false;
}

Updating Session Properties

The Session must already have the property, for example from Starting a new Game Session with Custom Properties.

C#

// Host, later on. "map" must be one of the properties the Session was created with
runner.SessionInfo.UpdateCustomProperties(new Dictionary<string, SessionProperty> {
  ["map"] = (int)GameMap.City,
});

For more examples, see Examples of API usage.

Lobby Info

LobbyInfo describes the Photon Cloud Lobby the local peer is in. A Lobby lists the Sessions published to it, and a peer in a Lobby receives that list through OnSessionListUpdated (see Session List). A peer joins a Lobby with NetworkRunner.JoinSessionLobby, before it calls StartGame.

Where To Read Lobby Info

API Description
NetworkRunner.LobbyInfo Record for the local peer. Never null. IsValid becomes true once JoinSessionLobby has joined the Lobby. Available on every peer.

Lobby Info Members

Member Description
IsValid True while the peer is in a Lobby. Set when the Photon Cloud confirms the join. Reset when the peer leaves the Lobby or enters a Session, by creating or joining it. Type bool.
Name Name of the Lobby (see Lobby Types). Null while IsValid is false. Type string.
Region Photon Cloud Region the peer is connected to, for example "eu". Null while IsValid is false. Type string.

Lobby Types

JoinSessionLobby takes a SessionLobby value that selects the Lobby:

SessionLobby LobbyInfo.Name Description
ClientServer "ClientServer" Default Lobby for Sessions started in Server, Host, Client and AutoHostOrClient mode.
Shared "Shared" Default Lobby for Sessions started in Shared mode.
Custom The lobbyID argument, trimmed Custom Lobby. JoinSessionLobby fails if lobbyID is null, empty or only whitespace.
Invalid - Not a Lobby. JoinSessionLobby fails.

All of them are Photon LobbyType.Default Lobbies.

Lobbies and Matchmaking

StartGame publishes or searches for a Session in a single Lobby, picked in this order:

  1. The Lobby the peer is in, if it called JoinSessionLobby before StartGame.
  2. StartGameArgs.CustomLobbyName, if set.
  3. The default Lobby for the Game Mode: "Shared" in Shared mode, "ClientServer" in every other mode.

A Session only appears in the session list of its own Lobby. Joining a random Session, by leaving StartGameArgs.SessionName empty, only matches Sessions from that Lobby.

Entering a Session takes the peer out of the Lobby: LobbyInfo.IsValid becomes false and OnSessionListUpdated is no longer called.

Notes

  • JoinSessionLobby connects to the Photon Cloud with its authentication and customAppSettings arguments. A later StartGame on the same runner reuses that connection, so StartGameArgs.AuthValues and StartGameArgs.CustomPhotonAppSettings are not applied.
  • JoinSessionLobby fails if the peer is already in a Session.
  • A failed JoinSessionLobby shuts the runner down and destroys its GameObject, the same as a failed StartGame.

Examples

Reading the Lobby Info

C#

public async Task ShowLobby(NetworkRunner runner) {
  var result = await runner.JoinSessionLobby(SessionLobby.Shared);

  if (result.Ok) {
    Debug.Log($"In Lobby {runner.LobbyInfo.Name}, Region {runner.LobbyInfo.Region}");
  } else {
    Debug.LogError($"Failed to join the Lobby: {result.ShutdownReason}");
  }
}

For listing and joining Sessions from a Lobby, including a Custom Lobby, see Join a Session from a Lobby.

Other NetworkRunner Properties

The NetworkRunner also provides some other Session and Photon Cloud related properties that can be used in-game, like:

Property Description
NetworkRunner.IsCloudReady Signals if the Local Peer is connected to Photon Cloud and ready to send operations. It is also true while the peer is in a Lobby or a Session, and false while it connects, joins or leaves.
NetworkRunner.UserId Holds the UserId of the Local Peer, or null while IsCloudReady is false. It is the UserId your application set in the AuthenticationValues, or the one returned on authentication, for example by your Authentication Service.
NetworkRunner.AuthenticationValues Holds a reference to the AuthenticationValues used to authenticate the local peer, or null while IsCloudReady is false. It is StartGameArgs.AuthValues, or the authentication argument of JoinSessionLobby when the peer joined a Lobby first.
NetworkRunner.CurrentConnectionType Describes the connection of a Client with its remote Server: Direct or Relayed. It is None while the Client is not connected, and always on the Server or Host. Keep in mind that in SharedMode, the clients always connect via relay.
NetworkRunner.NATType When the NAT Punchthrough System is enabled, Fusion will try to determine the current NAT Type of the current network where the local peer is running, this property exposes that information. NAT Types can be: Invalid, UdpBlocked, OpenInternet, FullCone or Symmetric. It stays Invalid in Shared mode, when NAT Punchthrough is disabled, and until the NAT Type is determined.
NetworkRunner.IsSharedModeMasterClient A boolean flag that indicates if the local peer is also the Master Client of a Shared Game Session. This is only valid when running in SharedMode and can be used to determine on which peer certain actions should happen based on the differentiation between other clients and the Master Client.

Game Session Browser

It is possible to create Game Session browsers within Fusion; however, they are strongly discouraged.

Game Session browsers were popular in the 90s and early 2000s. The fundamental design is still valid but nowadays their main purpose (finding a suitable game and joining it quickly) has been replaced with Matchmaking.

There are multiple reasons why Game Session browsers are discouraged:

  • there are security concerns;
  • retrieving a list of active Game Sessions is a performance-heavy operation for the servers;
  • the lists are always specific to the region to which a player is currently connected; and,
  • most importantly, it is an antiquated design pattern and better UX options are available today.

The up-to-date alternatives offered by Fusion Matchmaking API are:

  1. To fill / join a Game Session quickly: Join a random open room.
  2. To join a certain type of match: Join a random open room while also filtering using the Game Session properties.
  3. To have specific players join up and play together: Share the SessionName, for example as an invite code, and join the Game Session by name.

Unless the game has an abundance of community servers running which have their own custom / modded modes and maps, there is little to no reason to request a full list of rooms and make them available to the user through a Game Session browser.

Examples of API usage

Join a Random Session

To join any session, in cases where players just want to quickly join a Game, simply start the NetworkRunner and let it find an available Game Session without any extra parameters:

C#

public async Task StartPlayer(NetworkRunner runner) {

  var result = await runner.StartGame(new StartGameArgs() {
    GameMode = GameMode.AutoHostOrClient, // or GameMode.Shared
  });
  
  if (result.Ok) {
    // all good 
  } else {
    Debug.LogError($"Failed to Start: {result.ShutdownReason}");
  }
}

This way, the local peer will start and connect to a random Game Session. If none can be found, it will create a new one with a random Session Name (because it is using the GameMode.AutoHostOrClient). This is also valid if starting the NetworkRunner using the GameMode.Shared, for sessions in Shared Mode.

Join a Session in a Specific Region

Game Sessions only exist within a single Region, so players have to connect to the same region to play together. To override the Photon connection settings for a single NetworkRunner, copy the global PhotonAppSettings with GetCopy(), modify the copy and pass it via StartGameArgs.CustomPhotonAppSettings:

C#

FusionAppSettings appSettings = PhotonAppSettings.Global.AppSettings.GetCopy();
appSettings.FixedRegion = "eu";

var result = await runner.StartGame(new StartGameArgs() {
  GameMode = GameMode.Shared,
  CustomPhotonAppSettings = appSettings
});

Starting a new Game Session with Custom Properties

In this example a Host will create a Game Session with some custom properties, so that later, Clients can filter the Sessions using those properties.

C#

// Some predefined types used as values for the Game Session Properties
public enum GameType : int {
  FreeForAll,
  Team,
  Timed
}

public enum GameMap : int {
  Forest,
  City,
  Desert
}

// Utility method to start a Host using a defined GameMap and GameType
public async Task StartHost(NetworkRunner runner, GameMap gameMap, GameType gameType) {

  var customProps = new Dictionary<string, SessionProperty>();

  customProps["map"] = (int)gameMap;
  customProps["type"] = (int)gameType;

  var result = await runner.StartGame(new StartGameArgs() {
    GameMode = GameMode.Host,
    SessionProperties = customProps,
  });

  if (result.Ok) {
    // all good 
  } else {
    Debug.LogError($"Failed to Start: {result.ShutdownReason}");
  }
}

The sample code shows the use of Enums for the Custom Properties values of the Game Session, but this is just one way to add meaning to the values. Calling the runner.StartGame as a Host (GameMode = GameMode.Host) is enough to start a new session with a Random Name (as the SessionName argument was not passed) and by using the SessionProperties argument, Fusion will include those properties in the Session.

Join a Random Session with Filters

Considering the example code above, here is how to start a Client that will join any Game Session on any GameMap, but with a specific GameType. The startup code is basically the same, just the GameMode that is now set to GameMode.Client, and the customProps contains only the type key with the desired gameType value.

C#

public async Task StartClient(NetworkRunner runner, GameType gameType) {

  var customProps = new Dictionary<string, SessionProperty>() {
    { "type", (int)gameType }
  };

  var result = await runner.StartGame(new StartGameArgs() {
    GameMode = GameMode.Client,
    SessionProperties = customProps,
  });
  
  if (result.Ok) {
    // all good 
  } else {
    Debug.LogError($"Failed to Start: {result.ShutdownReason}");
  }
}

That is enough to make your client join a random Session with that specific GameType.

Join a Session from a Lobby

Another way to find the right Game Session is to provide a list of Sessions, allowing the player to choose one to join. Joining a Lobby is the way to go in this case, although we highly suggest avoiding this method if it is not strictly necessary. For most game types, joining a Session based on property filters is the best way, but Fusion makes Session listing pretty easy too.

Instead of using the usual flow and starting Fusion as described above, the Session listing follows a slightly different flow:

  1. Join a Lobby: using a Fusion Runner reference, just call NetworkRunner.JoinSessionLobby([SessionLobby], [string]) in order to make the peer connect to the Photon Cloud and join a specific Lobby. Its main arguments are:
    • sessionLobby: which can be one of the following values:
      1. ClientServer to join the default ClientServer Lobby;
      2. Shared to join the default Shared Lobby; and,
      3. Custom, used in conjunction with a custom lobbyID.
    • lobbyID: this should be a Custom Lobby Name used when creating a Game Session previously. It is only used with SessionLobby.Custom.
    • The other arguments, such as authentication and customAppSettings, are optional (see Lobby Info).

C#

// Utility method to Join the ClientServer Lobby
public async Task JoinLobby(NetworkRunner runner) {

  var result = await runner.JoinSessionLobby(SessionLobby.ClientServer);

  if (result.Ok) {
    // all good 
  } else {
    Debug.LogError($"Failed to Start: {result.ShutdownReason}");
  }
}

And as described before, it is possible for a Client to join the ClientServer, Shared or Custom lobbies this way. Just as an example, it is shown below how a Server/Host can create a Session in a custom Lobby:

C#

public async Task StartHost(NetworkRunner runner) {

  var result = await runner.StartGame(new StartGameArgs() {
    GameMode = GameMode.Host,
    CustomLobbyName = "MyCustomLobby"
  });

  if (result.Ok) {
    // all good 
  } else {
    Debug.LogError($"Failed to Start: {result.ShutdownReason}");
  }
}

And how a Client can join that custom Lobby:

C#

// Utility method to Join a Custom Lobby
public async Task JoinLobby(NetworkRunner runner) {

  var result = await runner.JoinSessionLobby(SessionLobby.Custom, "MyCustomLobby");

  if (result.Ok) {
    // all good 
  } else {
    Debug.LogError($"Failed to Start: {result.ShutdownReason}");
  }
}
  1. Get a list of Game Sessions: when working with Fusion, one of the main API entry points is the INetworkRunnerCallbacks, a special interface that Fusion uses to surface a series of different events, including the list of sessions from a Lobby. The OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList) callback will be invoked with the complete list of sessions from the Lobby every time the sessions change, either by the creation/removal of sessions or when the properties of a session are updated. The SessionInfo is of the same type described above. The list can then be shown, filtered, ordered, etc.

  2. Join a Session: with a selected Session to join, Fusion can be started using the usual NetworkRunner.StartGame(), but in this case, the SessionName used to start the client must be the one from the session. That way, the Client will join that particular Game Session.

    • Select the GameMode that matches the Session: GameMode.Client for a Session created by a Host or Server, and GameMode.Shared for a Shared Session. The Fusion Plugin disconnects a peer whose mode does not match with IncompatibleConfiguration. GameMode.AutoHostOrClient also works, but it creates a new Session as Host if the selected one no longer exists.
    • The SessionName field must be set to SessionInfo.Name, as this is the identifier of the Game Session.
    • All other parameters are optional and should be initialized accordingly.

C#

public class MyBehaviour : Fusion.Behaviour, INetworkRunnerCallbacks {

  // True once StartGame was called
  bool _joining;

  // other callbacks...

  // Receive the List of Sessions from the current Lobby
  public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList) {

    Debug.Log($"Session List Updated with {sessionList.Count} session(s)");

    // Ignore list updates while a join is in progress
    if (_joining) {
      return;
    }

    // Pick a Session with one of the methods below
    var session = FindFirstSession(sessionList); // OR FindSessionByType(sessionList, GameType.Team)

    // Check if there is any valid session
    if (session != null) {
      _joining = true;

      Debug.Log($"Joining {session.Name}");

      // Join
      runner.StartGame(new StartGameArgs() {
        GameMode    = GameMode.Client, // Client for a Host or Server Session, Shared for a Shared Session
        SessionName = session.Name,    // Session to Join
        // ...
      });
    }
  }

  // Example
  // First Session from the list
  SessionInfo FindFirstSession(List<SessionInfo> sessionList) {
    return sessionList.Count > 0 ? sessionList[0] : null;
  }

  // Example
  // First Session with a specific Custom Property
  SessionInfo FindSessionByType(List<SessionInfo> sessionList, GameType gameType) {

    foreach (var sessionItem in sessionList) {

      // Check for a specific Custom Property
      if (sessionItem.Properties.TryGetValue("type", out var propertyType) && propertyType.IsInt) {

        // Check for the desired Game Type
        if ((int)propertyType.PropertyValue == (int)gameType) {
          return sessionItem;
        }
      }
    }

    return null;
  }
}

Setup Dedicated Server Game Mode

Running Photon Fusion in Server Mode is pretty straightforward, but depending on the network characteristics of the hosting machine where the server is running, it might be necessary to set it up differently. For that reason, this document shows the three main ways to start Fusion with GameMode.Server. All three only apply while NAT Punchthrough is enabled. With StartGameArgs.DisableNATPunchthrough set, the peer only uses relayed connections, and Address and CustomPublicAddress are ignored.

  1. Full Automatic: The peer starts and binds to any available port given by the OS to the socket layer. This will work in most scenarios where a pre-defined port is not necessary. The STUN Protocol is used to resolve the Public EndPoint (IP:Port) of the peer. This is mostly suited for common networks that do not block ports by default, like domestic internet connections.

C#

runner.StartGame(new StartGameArgs() {
    GameMode = GameMode.Server
    // other args
});
  1. Pre-defined Local EndPoint & Automatic Public EndPoint: Similar to case 1, but here a particular Local EndPoint is set to be used by the Server. The peer will fail to start if any other service is bound to that same port, so make sure it is available. In the example code, the Server tries to bind to the EndPoint 192.168.0.10:27015, which must be an IP address associated with one of the host machine's network cards and an available port. If there is no need to specify a local IP but only the port, use NetAddress.Any(27015) (meaning 0.0.0.0:27015) instead. This is suited for scenarios with a restricted list of available ports that are open for communication on the host's firewall, so it is necessary to use one of these specific ports.

C#

using Fusion.Sockets;

runner.StartGame(new StartGameArgs() {
  GameMode = GameMode.Server,
  Address = NetAddress.CreateFromIpPort("192.168.0.10", 27015) // or NetAddress.Any(27015)
  // other args
});
  1. Pre-defined Local & Public EndPoint: Extending case 2, both the Local Endpoint and Public Endpoint of the peer can be set. Fusion completely bypasses the use of the STUN Protocol for Public EndPoint discovery and just relays the one passed as an argument. In the example, the peer binds to the same Local EndPoint as in case 2, but also uses the specific Public EndPoint 203.0.113.10:27030. The CustomPublicAddress argument is intended for scenarios where the hosting service already provides the mapping between Local and Public EndPoints.

C#

using Fusion.Sockets;

runner.StartGame(new StartGameArgs() {
  GameMode = GameMode.Server,
  Address = NetAddress.CreateFromIpPort("192.168.0.10", 27015),
  CustomPublicAddress = NetAddress.CreateFromIpPort("203.0.113.10", 27030)
  // other args
});

Last updated on

Back to top