2 - ロビー UI
このパートではロビーのユーザーインターフェース(UI)の作成を行います。
ネットワーキング自体に関わることではないので、説明するのは基本的な事項にとどめます。
Playボタン
現在、ロビーは自動的にクライアントをルームに接続しています。これは初期のテストではよかったのですが、本来はプレイを開始するか否か、またいつ開始するのか、ユーザーに選択肢があるほうが望ましいです。
ですので、そのためのボタンを作成しましょう。
- シーンLauncherを開きます。
- Unityメニュー'GameObject/UI/Button'を使用してUIボタンを作成し、Play Buttonと名付けます。
 Scene Hierarchy内にCanvasとEventSystem GameObjectが作成されました。
- Play Buttonの子テキスト値を「play」に書き換えます。
- Play Buttonを選択してButton Component内の- On Click ()セクションを検索します。
- 小さい「+」をクリックしてエントリーを追加します。
- LauncherGameObjectをHierarchyからFieldへドラッグします。
- ドロップダウンメニューLauncher.Connect()で選択します。
 ボタンをLauncherスクリプトと接続する処理が完了しました。ユーザーがこのボタンを押すと、Launcherスクリプトから「Connect()」メソッドが呼ばれます。
- スクリプトLauncherを開きます。
- Start()でConnect()を呼ぶ行を 削除します。
- スクリプトLauncherを保存し、同様にシーンも保存しましょう。
playを押しても、このボタンを押さないと接続されないことを確認してください。
プレイヤー名
典型的なゲームの最低限の重要な要件は、他のプレイヤーが対戦相手を確認できるようユーザーが自分の名前を入力することです。
このシンプルなタスクに、ひねりを加えます。名前の値を記憶できるようPlayerPrefsを使用します。こうすると、ユーザーがゲームを再度開いたときに、つけていた名前を復元できます。
様々なエリアに実装することでユーザ体験を向上でき、非常に便利で重要な機能です。
まずはプレイヤー名を管理・記憶するスクリプトを作成し、それから関連するUIを作成していきましょう。
PlayerNameInputFieldの作成
- 新しいC#スクリプトを作成し、 - PlayerNameInputFieldと名付けます。
- 以下がコンテンツの全てです。必要に応じて - PlayerNameInputFieldスクリプトを編集、保存します。- C# - using UnityEngine; using UnityEngine.UI; using Photon.Pun; using Photon.Realtime; using System.Collections; namespace Com.MyCompany.MyGame { /// <summary> /// Player name input field. Let the user input his name, will appear above the player in the game. /// </summary> [RequireComponent(typeof(InputField))] public class PlayerNameInputField : MonoBehaviour { #region Private Constants // Store the PlayerPref Key to avoid typos const string playerNamePrefKey = "PlayerName"; #endregion #region MonoBehaviour CallBacks /// <summary> /// MonoBehaviour method called on GameObject by Unity during initialization phase. /// </summary> void Start () { string defaultName = string.Empty; InputField _inputField = this.GetComponent<InputField>(); if (_inputField!=null) { if (PlayerPrefs.HasKey(playerNamePrefKey)) { defaultName = PlayerPrefs.GetString(playerNamePrefKey); _inputField.text = defaultName; } } PhotonNetwork.NickName = defaultName; } #endregion #region Public Methods /// <summary> /// Sets the name of the player, and save it in the PlayerPrefs for future sessions. /// </summary> /// <param name="value">The name of the Player</param> public void SetPlayerName(string value) { // #Important if (string.IsNullOrEmpty(value)) { Debug.LogError("Player Name is null or empty"); return; } PhotonNetwork.NickName = value; PlayerPrefs.SetString(playerNamePrefKey,value); } #endregion } }
このスクリプトを細かく見ていきましょう。
- PlayerPrefs.HasKey()、 PlayerPrefs.GetString() と PlayerPrefs.SetString(): 
 PlayerPrefsはペアになったエントリ-のシンプルな検索リストです(2列のエクセルシートのようなものです)。片方は- key(キー)、もう片方は- Value(値)です。
 Key(キー)は文字列で、完全に任意です。自由に名前を付けられますが、開発の間で変更することはできません。
 なのでPlayerPrefsキーは常に一か所で保管しておくべきです。[Static|変数の宣言を使用すればゲーム中に変更されないため便利です。一つを最後まで使用し、constとして宣言することもできますが、これはC#に十分に熟達してから行なってください。
ロジックは非常に簡潔です。
PlayerPrefsに特定のキーがある場合、それを取得し機能を起動する際にその値を直接入れることができます。このケースでは、起動時と編集時にこれでInputFieldを埋めます。PlayerPrefキーを現在のInputFieldの値で設定すれば、確実にローカルのユーザー端末に保管されるので後から取り戻すことができます(ユーザーが次にゲームを開いたとき)。
- スクリプトはこれを2か所で使用しています。名前がPlayerPrefsに保存されていることを確認した後のStart()時と、パブリックメソッド SetPlayerName()の内です。
 今の段階では、このメソッドを呼ぶものはありません。ユーザーがのInputFieldを編集するたびにそれを記録するよう、 InputFieldOnValueChange()とコールSetPlayerName()を結びつける必要があります。
 これはユーザがPlayを押している場合にのみ行うことができます。これにはスクリプトが必要なので、今回はわかりやすくするため簡潔なままにしましょう。
 また、これはユーザーの動作に関係なく、入力が記憶されることを意味します。これは、多くの場合に必要とされる挙動です。
プレイヤー名にUIを作成
- シーンLauncherにいることを確認してください。
- Unityメニュー'GameObject/UI/InputField'を使用してUI InputFieldを作成し、そのGameObjectを Name InputFieldと名付けます。
- RectTransform内のPosYの値を35に設定し、Play Buttonの上に配置されるようにします。
- Name InputFieldの- PlaceHolderの子を確認して、そのテキスト値を「Enter your Name...」に設定します。
- Name InputFieldGameObjectを選択します。
- これに作成したばかりのPlayerNameInputFieldスクリプトを追加します。
- InputFieldコンポーネント内のOn Value Change (String)セクションを選択します。
- 小さい「+」をクリックしてエントリーを追加します。
- 同じGameObjectにアタッチされているPlayerNameInputFieldコンポーネントをフィールドにドラッグします。
 
    - ドロップダウンメニューからDynamic Stringセクション内のPlayerNameInputField.SetPlayerNameを選択します。
- シーンを保存します。
これで、playを押して名前を入力した後に、プレイを停止して再度Playを押すと、入力した内容が表示されます。
ここまでの設定が完了しましたが、ユーザーエクスペリエンスの観点からいえば、接続の進捗のほか、接続時やルーム参加時に不具合があった場合のユーザーのフィードバックがまだ設定されていません。
接続の進捗
ここでは、簡潔にするためnameフィールドとplayボタンを非表示にして、接続時の"Connecting..."(接続中)のテキストで置き換え、必要に応じて切り替えます。
これを行うには、Playボタンとnameフィールドをグループ化して、そのグループを簡単に有効化・無効化できるようにします。
他の機能をこのグループに後で追加でき、また他の機能を追加してもロジックには影響しません。
- シーンLauncherにいることを確認してください。
- Unityメニュー'GameObject/UI/Panel'を使用してUIパネルを作成し、そのGameObjectをControl Panelと名付けます。
- Control Panelから- Imageと- Canvas Rendererコンポーネントを削除します。このパネルにはコンテンツは必要ですが、ビジュアルは不要です。
- Play Buttonと- Name InputFieldを- Control Panelにドラッグアンドドロップします。
 5.Unityのメニューの'GameObject/UI/Text'を使用してUI Textを作成し、そのGameObjectを- Progress Labelと名付けます。実行時に有効化または無効化できるので、ビジュアルが邪魔でも心配しないでください。
- Progress Labelの- Textコンポーネントを選択します。
- Alignmentを- center alignと- middle alignに設定します。
- Textの値を「Connecting...」に設定します。
- Colorを白もしくは背景から目立つ色に設定します。
- シーンを保存します。
この時点では、テストを行うためにControl PanelとProgress Labelを有効化または無効化して、さまざまな接続段階での動作を確認することができます。
これら2つのGameObjectの有効化を制御するため、スクリプトを編集してみましょう。
- スクリプト - Launcherを編集します。
- Public Fieldsリージョン内に、以下二つのプロパティを追加します。- C# - [Tooltip("The Ui Panel to let the user enter name, connect and play")] [SerializeField] private GameObject controlPanel; [Tooltip("The UI Label to inform the user that the connection is in progress")] [SerializeField] private GameObject progressLabel;
- Start()メソッドに以下を追加します。 - C# - progressLabel.SetActive(false); controlPanel.SetActive(true);
- Connect()メソッドの先頭に以下を追加します。- C# - progressLabel.SetActive(true); controlPanel.SetActive(false);
- OnDisconnected()メソッドの先頭に以下を追加します。- C# - progressLabel.SetActive(false); controlPanel.SetActive(true);
- スクリプト - Launcherを保存し、Unityがコンパイルを完了するのを待ちます。
- シーン - Launcherの中にいることを確認してください。
- Hierarchy内のGameObject - Launcherを選択します。
- Hierarchyの - Control Panelおよび- Progress Labelから、- Launcherコンポーネント内のそれぞれのフィールドにドラッグアンドドロップします。
- シーンを保存します。 
ここで、シーンを再生してみましょう。 コントロールパネルのみが表示され、Playをクリックすると、Progress Labelが表示されます。
これで、ロビーについての説明を完了しました。
ロビーにさらに機能を追加するには、ゲームそのものに切り替えて様々なシーンを作成し、ルームに入室する際に正しいレベルを読み込めるようにする必要があります。この方法は次のセクションで説明します。その後、ロビーシステムが完成します。