PUN Classic (v1)、PUN 2 和 Bolt 處於維護模式。 PUN 2 將支援 Unity 2019 至 2022,但不會添加新功能。 當然,您所有的 PUN & Bolt 專案可以用已知性能繼續運行使用。 對於任何即將開始或新的專案:請切換到 Photon Fusion 或 Quantum。

Bolt Matchmaking

Photon Bolt is high-level SDK for development of networked games, and one of the main features of such type of solution is the ability to do the matchmaking, in other words, the process of connecting players from different locations and devices on an online session, so they can play together. Bolt is no different and provides a set of simple, yet powerful, API to handle the management of rooms, helping developers to easily create games capable of maintaining game rooms where players can join and play side by side.

The main API entry point for the matchmaking capabilities of Photon Bolt can be used through the Bolt.Matchmaking.BoltMatchmaking class. It's responsible to handle the management of Bolt Sessions, creation and joining game rooms using the Photon Cloud services.

In this document, it's described how to get started with the BoltMatchmaking utility class. You can also check the API Reference here.

BoltMatchmaking API

  • BoltMatchmaking.CurrentSession: Gets the current session this peer is connected to.
  • BoltMatchmaking.CreateSession(string sessionID, IProtocolToken token, string sceneToLoad): Creates a Session using the current running Platform.
  • BoltMatchmaking.UpdateSession(IProtocolToken token): Updates the current session configuration.
  • BoltMatchmaking.JoinSession(UdpSession session, IProtocolToken token): Joins a Session using a UdpSession as reference.
  • BoltMatchmaking.JoinSession(string sessionID, IProtocolToken token): Joins a Session by name.
  • BoltMatchmaking.JoinRandomSession(IProtocolToken token): Joins a Session in a random fashion.
  • BoltMatchmaking.JoinRandomSession(UdpSessionFilter sessionFilter, IProtocolToken token): Joins a Session in a random fashion with filters.

Getting the Current Session

Looking at the current room in which the peer is connected to can be a useful routine, if you are looking for custom properties or just some additional information, for example. This data is exposed through the BoltMatchmaking.CurrentSession and must be invoked only after you are connected to a session. Here is an example how you can get this info:

C#

using Bolt.Matchmaking;

// ...

void Update()
{
    if (Input.GetKeyDown(KeyCode.I) && BoltNetwork.IsRunning)
    {
        var session = BoltMatchmaking.CurrentSession;

        BoltLog.Warn(session.HostName);

        var photonSession = session as PhotonSession;
        if (photonSession != null)
        {
            BoltLog.Warn("IsOpen: {0}, IsVisible: {1}", photonSession.IsOpen, photonSession.IsVisible);

            foreach(var key in photonSession.Properties.Keys)
            {
                BoltLog.Warn("{0} = {1}", key, photonSession.Properties[key]);
            }
        }
    }
}

// ...

Creating and Updating a Session

Creating a room is the starting point for the matchmaking, no session, no game. In Photon Bolt we use the server-client archetype where the server is responsible for maintaining the game running, exchanging data between the clients, and to publish the session, so other players can join it. In order to create the session, just call the BoltMatchmaking.CreateSession as shown below:

C#

// ...
void SetupSession(string map, int gameType)
{
    if (BoltNetwork.IsServer)
    {
        string matchName = Guid.NewGuid().ToString();

        // If you use Photon custom properties
        var customToken = new Bolt.Photon.PhotonRoomProperties();
        customToken.AddRoomProperty("m", map);
        customToken.AddRoomProperty("t", gameType);

        // Or if you use your own custom IProtocolToken
        var customToken = new MyServerToken();
        customToken.map = map;
        customToken.gameType = gameType;

        BoltMatchmaking.CreateSession(
            sessionID: matchName,
            sceneToLoad: map,
            token: customToken
        );
    }
    else
    {
        BoltLog.Warn("Only the server can create sessions");
    }
}
// ...

While the game is being played, the server can also update the metadata related to the session. This is useful if you want to share general settings of the current game that can be publicly available for clients playing the game and other possible clients that may want to join the match. To update the sessions info, just call BoltMatchmaking.UpdateSession:

C#

// ...
void UpdateSession(string map, int gameType)
{
    if (BoltNetwork.IsRunning && BoltNetwork.IsServer)
    {
        // If you use Photon custom properties
        var updateToken = new PhotonRoomProperties();
        updateToken.AddRoomProperty("m", map);
        updateToken.AddRoomProperty("t", gameType);

        // Or if you use your own custom IProtocolToken
        var updateToken = new MyServerToken();
        updateToken.map = map;
        updateToken.gameType = gameType;

        BoltMatchmaking.UpdateSession(updateToken);
    }
    else
    {
        BoltLog.Warn("Only the server can update sessions");
    }
}
// ...

Joining a Session

The counterpart of the matchmaking process takes place when the game clients look for sessions to join. Photon Bolt provides a variate of way to do this. In the following, we describe all the methodologies we've implemented to quickly make your game more fun with more player.

Join using a UdpSession as reference

This is the most basic way of connecting to another game session. When implementing a Bolt.GlobalEventListener, you get access to the SessionListUpdated(Map<Guid, UdpSession> sessionList) callback function that will be invoked every time the list of the available session is refreshed.

Within this method you can perform any kind of filtering on the sessions, so you are completely free to manage how they will be shown to the client. Using the UdpSession reference, you just need to call BoltMatchmaking.JoinSession, and optionally pass an IProtocolToken to be used during the connection process.

C#


public class Menu : Bolt.GlobalEventListener
{
    // ...

    public override void SessionListUpdated(Map<Guid, UdpSession> sessionList)
    {
        Debug.LogFormat("Session list updated: {0} total sessions", sessionList.Count);

        foreach (var session in sessionList)
        {
            UdpSession photonSession = session.Value as UdpSession;

            // Photon Session
            PhotonSession photonSession = udpSession as PhotonSession;
            if (photonSession != null)
            {
                // Those custom data comes from the PhotonRoomProperties Token
                object value_t = -1;
                object value_m = -1;

                if (photonSession.Properties.ContainsKey("t"))
                {
                    value_t = photonSession.Properties["t"];
                }

                if (photonSession.Properties.ContainsKey("m"))
                {
                    value_m = photonSession.Properties["m"];
                }

                BoltLog.Info("Joining Session with custom data {0}/{1}", value_t, value_m)
            }

            // Optional IProtocolToken
            var userToken = new UserToken();
            userToken.user = "user";
            userToken.password = "secret";

            BoltMatchmaking.JoinSession(photonSession, userToken);
        }
    }

    // ...
}

Join by Session Name

Photon Bolt also supports your client joining a room using just it's identifier, the same ID used to create the session on the server. In certain circumstances, your client doesn't want to wait for the list of sessions to be populated and look for the game he wants to enter, and if you have implemented or are using a system of Friend invite, for instance, this can be a solution for you. Connecting to a session this way is one of the quickest alternatives to join a specific game.

This is an overload of the BoltMatchmaking.JoinSession, that instead of receiving a UdpSession, receives a string with the room identifier, also with the capacity of receiving an IProtocolToken. Check the example below:

C#

// ...
void JoinSession(string sessionID, string user, string password)
{
    if (BoltNetwork.IsRunning && BoltNetwork.IsClient)
    {
        var userToken = new UserToken();
        userToken.user = user;
        userToken.password = password;

        BoltMatchmaking.JoinSession(sessionID, userToken);
    }
    else
    {
        BoltLog.Warn("Only a started client can join sessions");
    }
}
// ...

Join a Random Session

Some casual games have only a few types of gameplay and the player only wants to enter the game as soon as possible. For cases like this, joining a random session can be an interesting approach to accomplish the task. Using the BoltMatchmaking.JoinRandomSession method, Photon Bolt will try to join any available session always looking to fill the room as quickly as possible. Following the same pattern as the rest of the Join procedures, you have the option to pass an IProtocolToken object to the operation.

C#

void JoinRandomSession(string user, string password)
{
    if (BoltNetwork.IsRunning && BoltNetwork.IsClient)
    {
        var userToken = new UserToken();
        userToken.user = user;
        userToken.password = password;

        BoltMatchmaking.JoinRandomSession(userToken);
    }
    else
    {
        BoltLog.Warn("Only a started client can join sessions");
    }
}

Important to note that if there is no room available to join, the process will fail after the Room Join Timeout value (you can configure this value on the Bolt Settings) and the Bolt.GlobalEventListener.SessionConnectFailed() callback will be invoked.

Join a Random Session with Filters

Extending the functionality of the BoltMatchmaking.JoinRandomSession, it's also included an overloaded method capable of receiving an instance of the UdpSessionFilter class. This object is used to control the random join process, allowing the user to select the fill mode (read more about here), and also filter the set the of available rooms using custom parameters.

Keep in mind that you must create a session using the Bolt.Photon.PhotonRoomProperties as the token, using the custom properties, for the filter work properly when joining using this method. Here a simple example of joining a random session based on some parameters, also using an IProtocolToken to carry data from the client to server:

C#

void JoinRandomSession(string user, string password, string map, int gameType)
{
    if (BoltNetwork.IsRunning && BoltNetwork.IsClient)
    {
        var userToken = new UserToken();
        userToken.user = user;
        userToken.password = password;

        UdpSessionFilter filter = new UdpSessionFilter();

        filter.FillMode = UdpSessionFillMode.Random; // Fill, Random or Serial
        filter["m"] = map;
        filter["t"] = gameType;

        BoltMatchmaking.JoinRandomSession(filter, userToken);
    }
    else
    {
        BoltLog.Warn("Only a started client can join sessions");
    }
}

Matchmaking Metadata

Some platforms integrated with Photon Bolt can generate some metadata related specifically to the running integration. In most cases, this is custom information that is not available for all platforms. With this in mind, we've included in the BoltMatchmaking utility class a new field, CurrentMetadata, a dictionary that will contain any meta information exposed by the active platform. The list of available data may grow over time, feel free to request new information.

For example, we've exposed the current region that your peer is connected when using the Photon Cloud platform (PhotonPlatform), as shown below:

C#

public string GetCurrentRegion()
{
    if (BoltMatchmaking.CurrentMetadata != null && BoltMatchmaking.CurrentMetadata.ContainsKey("Region"))
    {
        return BoltMatchmaking.CurrentMetadata["Region"] as string;
    }

    return null;
}

Currently available metadata is:

  • PhotonPlatform:
    • Region: current connected Region. More info here;
    • Data: custom authentication data;
    • UserId: peer User ID. More info here;
    • Nickname: peer Nickname;
    • LobbyStatistics: extra Lobby information. More info here;
Back to top