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 ()
セクションを検索します。- 小さい「+」をクリックしてエントリーを追加します。
Launcher
GameObjectを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 InputField
GameObjectを選択します。- これに作成したばかりの
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が表示されます。
これで、ロビーについての説明を完了しました。
ロビーにさらに機能を追加するには、ゲームそのものに切り替えて様々なシーンを作成し、ルームに入室する際に正しいレベルを読み込めるようにする必要があります。この方法は次のセクションで説明します。その後、ロビーシステムが完成します。