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"); return; } Debug.LogFormat("PhotonNetwork : Loading Level : {0}", PhotonNetwork.CurrentRoom.PlayerCount); PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.CurrentRoom.PlayerCount); } #endregion
GameManager
スクリプトを保存します。
このメソッドを呼び出すとき、入室しているルームのPlayerCount
プロパティにもとづいて、適切なルームを読み込みます。
重要な注意点が2つあります。
- PhotonNetwork.LoadLevel()を呼び出すのは、マスタークライアントの場合のみにしてください。初めに自身がPhotonNetwork.IsMasterClientを使用しているマスタークライアントであることを確認します。
これを確認するのは、呼び出しを元の責任です。この点については、このセクションの事項で説明します。 - 希望のレベルを読み込むには、PhotonNetwork.LoadLevel()を使用します。このゲームではPhotonNetwork.AutomaticallySyncSceneを有効化しているので、ルーム内の接続中の全てのクライアントに、このレベルを読み込むには、Photonに依存するようにします。Unityを直接使用することはありません。
適切なレベルを読み込む機能を設定したので、プレイヤーの接続や切断と連携させてみましょう。
プレイヤーの接続を監視
このチュートリアルの前半ではPhotonのコールバックを取得する様々な方法を説明しました。GameManager
はプレイヤーの接続と切断をリッスンする必要があります。
これを実装してみましょう。
GameManager
スクリプトを開きます。次のPhotonコールバックを追加し、
GameManager
スクリプトを保存します。C#
#region Photon Callbacks public override void OnPlayerEnteredRoom(Player other) { Debug.LogFormat("OnPlayerEnteredRoom() {0}", other.NickName); // not seen if you're the player connecting if (PhotonNetwork.IsMasterClient) { Debug.LogFormat("OnPlayerEnteredRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom LoadArena(); } } public override void OnPlayerLeftRoom(Player other) { Debug.LogFormat("OnPlayerLeftRoom() {0}", other.NickName); // seen when other disconnects if (PhotonNetwork.IsMasterClient) { Debug.LogFormat("OnPlayerLeftRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom LoadArena(); } } #endregion
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.CurrentRoom.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コンソールで"PUN Basics Tutorial/Launcher: OnConnectedToMaster() was called by PUN"がログに記録されているのを確認します。
Launcher
シーンを停止します。- ログエントリー"PUN Basics Tutoria/Launcher: OnConnectedToMaster()をダブルクリックしてください。スクリプトが読み込まれ、デバッグコールの行が指し示されます。
- つまり、接続済みの通知を受けるたびに、自動的に希望ではないランダムなルームに参加してしまいます。
この問題を修正するには、コンテキストに注意をしなければいけません。ユーザーが「Play」ボタンをクリックすると、接続手順がユーザーから開始されたことがわかるように目立つようにフラグをたてる必要があります。
その後、様々なPhotonコールバック内で必要に応じて動作するためにこのフラグを確認します。
スクリプト
Launcher
を編集します。プライベートFieldリージョンで新しいプロパティを作成します。
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();
result:
C#
public void Connect()
{
progressLabel.SetActive(true);
controlPanel.SetActive(false);
if (PhotonNetwork.IsConnected)
{
PhotonNetwork.JoinRandomRoom();
}
else
{
isConnecting = PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.GameVersion = gameVersion;
}
}
OnConnectedToMaster()
メソッド内で以下のようにif
文でPhotonNetwork.JoinRandomRoom()
を囲みます。
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 OnJoinRandomFailed()
PhotonNetwork.JoinRandomRoom();
isConnecting = false;
}
OnDisconnected
メソッドでisConnecting
をfalse
に設定します。- スクリプト
Launcher
を保存します。
再びテストを行い、Launcherシーンを実行して、ロビーとゲームを行き来すると、全てが順調だとわかります。
シーンの自動同期をテストするには、アプリケーションをパブリッシュし(テストを迅速に行うには、デスクトップにパブリッシュします)、2人のプレイヤーをルームに接続および参加させるためUnityに沿って実行する必要があります。
もしUnityエディタが先にルームを作成すると、それがマスタークライアントとなります。そして、パブリッシュされたインスタンスにUnityコンソールで接続すると、"PhotonNetwork : Loading Level : 1"と、その後に"PhotonNetwork : Loading Level : 2"を取得した点を確認できます。
多くの点を説明し終えましたが、まだ半分が残っています。
次のセクションではプレイヤー自身について説明します。
多くの点を説明していますので時々パソコンから離れて休憩してください!
特定の機能について質問がある場合や、チュートリアル中にこのドキュメントで説明していないエラーや問題が発生した場合は、フォーラムに投稿してください喜んでお手伝いさせていただきます!
Back to top