Matchmaking API
はじめに
マルチプレイヤーゲームを作る上で重要なことは、同じスキルやレベルのプレイヤー、同じゲームタイプやマップをプレイしたいプレイヤーを簡単にマッチングさせ、ゲーム内の体験を出来るだけ楽しくすることです。
この目的のために、Photon Fusionは、完璧なマッチングを求めるプレイヤーに最高の体験を提供するためのAPIコールを公開しています。
Photon Fusionは、Photon Cloudと透過的に連動しています。Photonバックエンドサービスとのやりとりは、ほとんど内部で自動的に行われます。
このページでは、Fusion Matchmaking APIについて説明します。このAPIは、プレイヤーが希望するゲームプレイ体験に基づいて最適なSession
をフィルタリング/参加するために使用するカスタムプロパティを持つGame Session
を作成/更新するために使用されます。
用語集
以下は、このドキュメントで使用されている、Matchmaking API
の正しい使い方に直接関係する用語の説明です。
Game Session
: または単にSession
は、プレイヤーがマッチをプレイするために集まる場所、またはコミュニケーションをとる場所です。これはPhoton Cloudに公開され、他のクライアントが特定のマッチを検索、フィルタリング、参加できるようにするためのものです。セッションの外でのコミュニケーションは不可能で、どのクライアントも1つのルームでしか活動できません。ゲームセッションは次のようなプロパティとメソッドを持ちます: 名前による作成と参加、カスタムプロパティ、最大プレイヤー数、非表示(Lobby
に表示しない)または表示、閉じる(誰も入れない)または開くことが可能。Lobby
:Session
の仮想的なコンテナまたは "リスト" 。複数のロビーを使って異なるゲームタイプでセッションを分割することも可能です。Fusionでは、ClientServer Mode
(Server
,Host
,Client
) でSession
を作成すると、ClientServer
という特定のLobby
に作成され、Shared Mode
で作成すると、Shared
というLobby
に作成されることになります。プレイヤーはLobby
内で通信することはできず、他のクライアントがロビーにいることも知ることはできません。クライアントは、Lobby
、Session
、またはそのいずれかにのみ参加することができます。
ゲームセッションの作成と参加
Game Session
の作成と参加は同じ手続きの2部構成になっており、そのルールは単純です。
1. 指定した SessionName
を持つ Session
が存在しない場合、その SessionName
で新しいセッションを作成します (以下に説明するように、すべての場合ではありません)
2. ピアがその SessionName
を持つセッションに参加する。
APIに関しては、新しいFusion Simulationが開始されると、これら全てが自動的に行われます。新規にセッションを作成する際に、セッションをカスタマイズするために使用できる主な引数は、以下のとおりです。
C#
NetworkRunner.StartGame(new StartGameArgs {
// other args...
SessionName = [string]
SessionProperties = [Dictionary<string, SessionProperty>],
CustomLobbyName = [string],
PlayerCount = [int],
DisableNATPunchthrough = [bool],
CustomSTUNServer = [string],
AuthValues = [AuthenticationValues],
DisableClientSessionCreation = [bool]
});
Game Session
に関連するすべての引数は任意であり、それぞれのデフォルト値は以下のとおりです。
- SessionName:
Game Session
の名前です。Photon Cloud
上でセッションを識別し、Region内で一意である必要があります。 デフォルトでは、Name
が設定されていない場合、Fusionはセッションを識別するためにランダムなGUID
を生成します。2つのケースが考えられます。
特定の
SessionName
で開始すると、Fusion は 常に そのName
を持つSession
を作成/参加させようとします。これはFusionの重要な要素です。クライアントピアはセッションを作成することができ、(これをlate-join-serverと呼びます)サーバはクライアントが作成したセッションに事前に参加することができます。SessionName
を指定しない場合、Fusion はHost
,Server
,Shared
ゲームモードで起動した場合のみ、新しいセッションを作成/参加し、Client
モードで起動した場合はランダムなSession
に参加しようと試みます。
- SessionProperties:
Session
のCustom Properties
は、ゲームモード/タイプや現在読み込まれているマップなど、Game Session
に関するメタデータを含める方法です。このプロパティはSession
を作成する際に、常にSession Lobby
に公開されることを覚えておいてください。この引数のもう一つの使い方は、Client
がランダムなSession
に参加する際のマッチングフィルターとして使用します。トラフィックを最小限にするために、常にProperties Keys
の文字列をできるだけ短く保つようにしてください。デフォルトでは、Session Custom Properties
は空で、余分な情報は含まれていません。 - CustomLobbyName:
Lobby
とは、似たようなGame Sessions
を集約するためのもので、例えば異なるゲームタイプのセッションを分離するために使用することができます。この引数で、Session
が関連付けられるカスタムLobby Name
を設定します。デフォルトでは、Fusion はGameMode
に基づいてSession
を分離します。Session
がHost
,Server
,Client
ゲームモードで作成された場合はClientServer Lobby
で、Shared
ゲームモードで作成された場合はShared Lobby
で分離されます。 - PlayerCount: この
Session
に接続できるクライアントの最大人数を定義します。このパラメータは新しいSession
を作成するときのみ使用され、デフォルトではNetworkProjectConfig/Simulation
のDefault Players
設定で設定された値が使用されます。 - DisableNATPunchthrough: Photon Fusionに実装されているNATパンチスルーシステムを無効にするためのブーリアンフラグです。これにより、クライアントとサーバ間で中継された接続が行われるようになります。ゲームサーバに
true
を設定すると、全てのクライアントがリレー接続され、Client
に設定すると、特定のピアだけがリレー接続されます。 - CustomSTUNServer: ピアのリフレクティブアドレスを解決するために使用するカスタムSTUNサーバーを指定します。
- AuthValues: 外部サービスを使用してピアを認証するために使用されるカスタム認証値です。認証は、
Photon Dashboard
で特定のApplication ID
に対して事前に設定されたサービスを使用して行われます。 - DisableClientSessionCreation:
Client
として起動するピアが、SessionName
を指定しても新しいSession
を作成しないようにするためのブール型フラグです。デフォルトでは、クライアントはSession
を作成し、Server
が参加するのを待つことができますが、このフラグを使用すると、この動作を無効にすることができます。
このAPIでは、ランダムに、あるいは特定の SessionName
で Game Session
を作成して参加することができます。これは、たとえば Game Invitation を受け取ったときに使用することができますが、カスタムプロパティを使用して Session
をフィルタリングし、特定の構成のゲームにのみ参加することもできます。
これにより、セッションを管理する際の柔軟性が格段に向上します。
以下の表は、シミュレーション開始時の SessionName
と GameMode
に依存する Game Session
の作成と参加について、Fusionがどのように処理するかをまとめたものです。
有効なセッション名 | ゲームモード | 動作 |
---|---|---|
はい | ホスト/サーバー | セッションを作成する |
クライアント | セッションに参加する、見つからない場合は失敗する | |
共有 | セッションに参加する、見つからない場合は作成する | |
いいえ | ホスト/サーバー | ランダムな名前でセッションを作成する |
クライアント | ランダムなセッションに参加する、見つからなければ失敗 | |
共有 | ランダムなセッションに参加する、見つからない場合はランダムな名前でセッションを作成する |
ゲームセッション情報の取得と更新
Fusion では、現在接続している Game Session
の Name
や Region
など、様々な情報を提供しています。
これらのデータは、NetworkRunner
の SessionInfo
プロパティから直接取得することができます。
以下に、SessionInfo
タイプで利用可能な全ての欄を示します。
IsValid [bool{get}]
:SessionInfo
が読み込み/書き込みの準備ができているかどうかを示す。Name [string{get}]
:セッション名
Region [string{get}]
: 現在接続しているRegion
Properties [Dictionary<string, SessionProperty>{get}]
: 現在のSession Custom Properties
を含む読み込み専用の辞書。これらのプロパティを更新するには、SessionInfo.UpdateCustomProperties(Dictionary<string, SessionProperty>)
メソッドを使用して、新しいプロパティセットを渡してください。IsVisible [bool{get,set}]
:Session
がLobby
上でVisible
であるかどうかのシグナルを返します。セッションを不可視にするには、このプロパティを変更するだけです。IsOpen [bool{get,set}]
:Session
がOpen
で参加できるかどうかのシグナルです。セッションを閉じたり開いたりするには、このプロパティを変更するだけでよい。PlayerCount [int{get}]
:Session
にいる現在のPlayers
の数です。ロビーでのみ利用可能です。MaxPlayers [int{get}]
:セッション
に参加できるピアの最大数です。この値にはサーバー/ホスト
ピアのスロットも含まれます。*ロビーでのみ利用可能です。
Session
情報と、主に Custom Properties
は、Matchmaking の目的のみに使用し、ゲームクライアントとゲームの状態を同期させるtためには **決して ** 使用しないでください。そのような使い方は非常にお勧めできません。
ゲームプレイに関連する情報をセッション全体で交換する必要がある場合、Fusionには、グローバルなNetworkObject
を用意したり、ワンショットのデータにはRPC
を使用するなど、様々なオプションが用意されています。
また、NetworkRunner
は、ゲーム内で使用できる Session
や Photon Cloud
関連のプロパティもいくつか提供しています。例えば:
NetworkRunner.IsCloudReady
: ローカルピアがPhoton Cloud
に接続し、ルームの作成/参加やロビーへの参加が可能かどうかのシグナル。NetworkRunner.UserId
: 認証されたローカルピアのUserId
を保持。この情報は、アプリケーションで使用される認証サービスから取得されます。NetworkRunner.AuthenticationValues
: Fusionの起動時にローカルピアの認証に使用されたAuthenticationValues
のリファレンスを保持。NetworkRunner.CurrentConnectionType
: ピアが現在使用している Connection Type を記述します。リモートのServer
との接続はDirect
またはRelayed
です。SharedMode
では、クライアントは常にリレー経由で接続することに留意してください。NetworkRunner.NATType
: NAT Punchthrough Systemが有効な場合、Fusionはローカルピアが動作しているネットワークの現在のNAT Typeを判断しようとします。NAT タイプは、Invalid
、UdpBlocked
、OpenInternet
、FullCone
またはSymmetric
です。NetworkRunner.IsSharedModeMasterClient
: ローカルピアがShared Game Session
のMaster Client
でもあるかどうかを表すブーリアンフラグです。これはSharedMode
で動作しているときのみ有効で、他のクライアントとMaster Client
の区別に基づいて、どのピアで特定のアクションを発生させるかを決定するために使用することができます。
ロビーからゲームセッションに参加する
正しいGame Session
を見つけるもう一つの方法は、Sessions
のリストを提供し、プレイヤーが参加するセッションを選択できるようにすることです。
この場合、ロビー
に参加するのが良い方法ですが、必要でない場合はこの方法を使わないことをお勧めします。
ほとんどのゲームタイプでは、プロパティフィルタに基づいたSession
への参加が最適ですが、FusionではSession Listing
も簡単に行うことができます。
通常のフローを使い、上記のようにFusionを起動するのではなく、Session
Listingは少し違ったフローをたどります。
- Join a Lobby: Fusion Runner のリファレンスを使い、
NetworkRunner.JoinSessionLobby(SessionLobby, [string])
をコールするだけで、ローカルピアが Photon Cloud に接続し、特定のLobby
に入室できるようにします。このメソッドは2つの引数を受け取ります。
SessionLobby
: 以下の値のいずれかを指定することができます。ClientServer
で、デフォルトのClientServer Lobby
に参加。
2.Shared
はデフォルトのShared Lobby
に参加。Custom
は、Custom Lobby Name
と共に使用。
LobbyName
: これは以前のGame Session
を作成するときに使用したCustom Lobby Name
であるべきです。
- ゲームセッションのリストを取得する: Fusion を使う場合、主な API エントリポイントの一つは
INetworkRunnerCallbacks
で、これは Fusion がLobby
からのセッションリストを含む一連の異なるイベントを表示するために使用する特別なインターフェースです。OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList)
コールバックは、セッションの作成/削除やセッションのプロパティが更新されるなど、セッションのリストが変更されるたびに呼び出されます。SessionInfo
は上記と同じタイプです。その後、リストの表示、フィルタリング、順序付けなどを行うことができます。 - Join a Session: 参加する
Session
を選択すると、通常のNetworkRunner.StartGame()
を使って Fusion を起動することができますが、この場合、クライアントの起動に使うSessionName
はセッションのものでなければなりません。そうすれば、Client
はこの特定のGame Session
に参加することになります。- 通常通り、正しい
GameMode
を選択します。ピアはSession
に参加するので、GameMode.Client
またはGameMode.Shared
モードのどちらかでなければなりません。
- 通常通り、正しい
SessionName
欄にはSessionInfo.Name
を設定する必要があります。これはGame Session
の識別子となるためです。- 他のすべてのパラメータは任意で、例えば
SceneObjectProvider
のように、適宜初期化する必要があります。
APIの使用例
ランダムセッションにジョインする
セッションにジョインするためには(プレイヤーがゲームにさっとジョインする場合)、NetworkRunner
を開始して、パラメータを加えずに利用可能なGame Session
を探します。
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}");
}
}
こうすることで、ローカルピアがランダムなGame Session
を開始して接続できるようになります。何も見つからない場合は、ランダムなSession Name
で新しいセッションが作成されます(GameMode.AutoHostOrClient
を使用しているため)。Sharedモードのセッションでも、GameMode.Shared
を使用してNetworkRunner
を起動していた場合、こちらは有効です。
カスタムプロパティで新しいゲームセッションを開始する
この例では、Host
がいくつかのカスタムプロパティを持つ Game Session
を作成します。後で Clients
がこれらのプロパティを使用して Sessions
をフィルタリングすることができます。
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}");
}
}
サンプルコードでは Game Session
の Custom Properties
の値に Enums
を使用していますが、これは値に意味を持たせるための一つの方法に過ぎません。
Runner.StartGame
をHost
として呼び出す (GameMode = GameMode.Host
) だけで、Random Name
(SessionName
引数が渡されなかったため) で新しいセッションが開始され、SessionProperties
引数を使用すると、Fusion は Session
にそれらのプロパティを含めることができます。
フィルタを使ってランダムセッションに参加する
上記のサンプルコードから、特定のGameTypeを持つ、任意のGameMap上の任意のゲームセッションに参加するClient
を起動する方法を説明します。
スタートアップのコードは基本的に同じで、GameMode
が GameMode.Client
に設定され、customProps
には type
キーと希望の gameType
値のみが含まれています。
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}");
}
}
これだけで、クライアントはその特定の GameType
のランダムな Session
に参加できるようになります。
ロビーからセッションに参加する
Fusionをすぐに起動するのではなく、Lobby
からSession
を取得するには、別のメソッドセットが必要です。
以下のサンプルコードでは、Fusion Runner が Photon Cloud に接続し、あらかじめ定義された ClientServer
ロビーに参加するようにしています。
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}");
}
}
また、前述したように、この方法で ClientServer
, Shared
, Custom
ロビーに Client
が参加することが可能です。
以下のように、サーバ/ホストが Custom
ロビーで Session
を作成する場合です。
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}");
}
}
Client
の Join 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}");
}
}
接続が確立すると、Fusion Runner は登録された全ての INetworkRunnerCallbacks
に対して OnSessionListUpdated
コールバックを呼び出します。
以下に、リストの最初の Session
に参加する方法を示すサンプルコードがあります。
C#
public class MyBehaviour : Fusion.Behaviour, INetworkRunnerCallbacks {
// 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)");
foreach (var session in sessionList) {
Debug.Log($"Joining {session.Name}");
// This call will make Fusion join the first session as a Client
runner.StartGame(new StartGameArgs() {
GameMode = GameMode.Client, // Client GameMode
SessionName = session.Name, // Session to Join
SceneObjectProvider = GetSceneProvider(runner), // Scene Provider
DisableClientSessionCreation = true, // Make sure the client will never create a Session
});
return;
}
}
}
Back to top