4-ゲームマネージャーとレベル
このセクションでは、現在のルームでプレイしているプレイヤーの数に基づいて、様々なレベルの読み込みを処理する追加機能について説明します。
アリーナルーチンの読み込み
4つの異なるルームを作成し、最後の文字がプレイヤーの数になるよう命名したため、ルーム内の現在のプレイヤ数と関連シーンの結合が非常に容易になりました。
これは「設定より規約」という、とても効果的な技術です。「設定」にもとづくアプローチをとった場合には、ルーム内の特定のプレイヤー数のシーン名をルックアップテーブルリストで維持するなどの方法になります。
スクリプトはそのリストを確認し、名前と関係ないシーンを返すことになります。
「設定」は基本的により多くのスクリプトを必要とするので、ここでは関連のない機能でコードを乱すことのないよう「規約」を使用します。
GameManager
スクリプトを開きます。今回のために作成するプライベートメソッド専用の新たなリージョン内に、新しいメソッドを追加してみましょう。
GameManager
スクリプトの保存を忘れないでください。C#
#region Private Methods void LoadArena() { if (!PhotonNetwork.isMasterClient) { Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client"); } Debug.Log("PhotonNetwork : Loading Level : " + PhotonNetwork.room.PlayerCount); PhotonNetwork.LoadLevel("Room for "+PhotonNetwork.room.playerCount); } #endregion
GameManager
スクリプトを保存します。
このメソッドを呼び出すとき、入室しているルームのPlayerCountプロパティにもとづいて、適切なルームを読み込みます。
重要な注意点が2つあります。
- PhotonNetwork.LoadLevel()はマスターの場合のみ呼び出されるべきです。このため、まず自身がPhotonNetwork.isMasterClientを使用しているマスターである点を確認します。
これを確認するのは、呼び出し元の責任です。この点については、このセクションの次項で説明します。 - 希望のレベルを読み込むには、PhotonNetwork.LoadLevel()を使用します。このゲームではPhotonNetwork.automaticallySyncSceneを有効化済みで、ルーム内のすべての接続済みクライアントにこのレベルを読み込むには、Photonに依存するようにします。Unityを直接使用することはありません。
適切なレベルを読み込む機能を設定したので、この機能をプレイヤーの接続や切断と連携させてみましょう。
プレイヤーの接続を監視
現在、GameManager
スクリプトは通常の MonoBehaviourです。チュートリアルの前の部分でPhotonのコールバックを取得するための様々な方法を説明しました。GameManager
は、プレイヤーの接続や切断をリッスンする必要があります。
これを実装してみましょう。
GameManager
スクリプトを開きます。基本クラスをMonoBehaviourからPhoton.PunBehaviourに変更します。
C#
public class GameManager : Photon.PunBehaviour {
以下のPhotonコールバックメッセージを追加し、
GameManager
スクリプトを保存します。C#
#region Photon Messages public override void OnPhotonPlayerConnected(PhotonPlayer other) { Debug.Log("OnPhotonPlayerConnected() " + other.NickName); // not seen if you're the player connecting if (PhotonNetwork.isMasterClient) { Debug.Log("OnPhotonPlayerConnected isMasterClient " + PhotonNetwork.isMasterClient); // called before OnPhotonPlayerDisconnected LoadArena(); } } public override void OnPhotonPlayerDisconnected(PhotonPlayer other) { Debug.Log("OnPhotonPlayerDisconnected() " + other.NickName); // seen when other disconnects if (PhotonNetwork.isMasterClient) { Debug.Log("OnPhotonPlayerDisconnected isMasterClient " + PhotonNetwork.isMasterClient); // called before OnPhotonPlayerDisconnected LoadArena(); } } #endregion
Photon.PunBehaviourで定義されているため、
OnLeftRoom
シグネチャを以下のように変更します。C#
public override void OnLeftRoom()
GameManager
スクリプトを保存します。
設定が完了しました。プレイヤーがルームに入室または退室する度に通知され、上記で構築したLoadArena()
メソッドを呼び出します。
ただしLoadArena()を呼び出すのは、PhotonNetwork.isMasterClientを使用しているマスターである場合のみです。
ロビーに戻り、ルームに参加するときに正しいシーンを読み込めるようにしましょう。
ロビーからアリーナを読み込み
スクリプト
Launcher
を編集します。OnJoinedRoom()
メソッドに以下を追加します。C#
// #Critical: We only load if we are the first player, else we rely on PhotonNetwork.automaticallySyncScene to sync our instance scene. if (PhotonNetwork.room.PlayerCount == 1) { Debug.Log("We load the 'Room for 1' "); // #Critical // Load the Room Level. PhotonNetwork.LoadLevel("Room for 1"); }
スクリプト
Launcher
を保存します。
これをテストしてみましょう。シーンLauncher
を開いて実行します。「Play」をクリックし、システムを接続させてルームに参加します。
これでロビーが動作するようになりました。しかし、ルームを退出してロビーに戻ってくると、自動的に再参加してしまいます。この問題に対処しましょう。
理由が分からない場合は、「簡単に」ログを分析してください。
上記で「」をつけたのは、問題を概観して確認すべき場所を把握し、デバッグの方法を理解するには経験が必要なためです。
自分で試してみてください。問題の原因を見つけることができない場合は、以下をおこなってみましょう。
Launcher
シーンを実行します。- 「Play」ボタンを押し、ルームに参加して「Room for 1」が読み込まれるまで待ちます。
- Unityコンソールをクリアします。
- 「Leave Room」を押します。
- Unityコンソールで、"DemoAnimator/Launcher: OnConnectedToMaster() was called by PUN"がログに記録されている点を確認します。
Launcher
シーンを停止します。- ログエントリー「DemoAnimator/Launcher: OnConnectedToMaster() was called by PUN」をダブルクリックしてください。スクリプトが読み込まれ、デバッグコールの行が指し示されます。
- つまり、接続済みの通知を受けるたびに、自動的にJoinRandomRoomに参加しますが、これは修正する必要があります。
これを修正するには、コンテキストを認識する必要があります。ユーザーが「Play」ボタンをクリックすると、接続手順がユーザーから開始されたことを認識するためにフラグを立てる必要があります。
次に、様々なPhotonコールバック内で必要に応じて行動するために、このフラグを確認します。
スクリプト
Launcher
を編集します。プライベート変数リージョンで新しいプロパティを作成します。
C#
/// <summary> /// Keep track of the current process. Since connection is asynchronous and is based on several callbacks from Photon, /// we need to keep track of this to properly adjust the behavior when we receive call back by Photon. /// Typically this is used for the OnConnectedToMaster() callback. /// </summary> bool isConnecting;
connect()
メソッドの先頭に、以下を追加します。
C#
// keep track of the will to join a room, because when we come back from the game we will get a callback that we are connected, so we need to know what to do then
isConnecting = PhotonNetwork.ConnectUsingSettings(_gameVersion);
result:
C#
public void Connect()
{
progressLabel.SetActive(true);
controlPanel.SetActive(false);
if (PhotonNetwork.IsConnected)
{
PhotonNetwork.JoinRandomRoom();
}
else
{
isConnecting = PhotonNetwork.ConnectUsingSettings(_gameVersion);
}
}
OnConnectedToMaster()
メソッドで、以下のようにPhotonNetwork.JoinRandomRoom()
をif
文で囲みます。
C#
// we don't want to do anything if we are not attempting to join a room.
// this case where isConnecting is false is typically when you lost or quit the game, when this level is loaded, OnConnectedToMaster will be called, in that case
// we don't want to do anything.
if (isConnecting)
{
// #Critical: The first we try to do is to join a potential existing room. If there is, good, else, we'll be called back with OnPhotonRandomJoinFailed()
PhotonNetwork.JoinRandomRoom();
isConnecting = false;
}
OnDisconnectedFromPhoton
メソッドでisConnecting
をfalse
に設定します。- スクリプト
Launcher
を保存します。
再びテストをおこない、Launcherシーンを実行してロビーとゲームの間を行き来すると、すべてが順調だと分かります。
シーンの自動同期をテストするにはアプリケーションをパブリッシュし(テストを迅速におこなうには、デスクトップにパブリッシュします)、二人のプレイヤーをルームに接続および参加させるためUnityに沿って実行する必要があります。
Unityエディターが先にルームを作成する場合には、それがマスタークライアントになります。そして、パブリッシュされたインスタンスにUnityコンソールで接続すると"PhotonNetwork : Loading Level : 1"と、その後に "PhotonNetwork : Loading Level : 2"を取得した点を確認できます。
多くの点を説明し終えましたが、まだ半分が残っています。次のセクションではプレイヤー自身について説明します。
多くの点を説明していますので時々コンピュータから離れて休憩を取ってください!
特定の機能について質問がある場合や、チュートリアル中にこのドキュメントで説明していないエラーや問題が発生した場合は、フォーラムに投稿してください。喜んでお手伝いさせていただきます!
Back to top