グーグルアドセンス

広告

UnityとPhoton Pun2で作るオンラインアクションゲーム制作12 Lobbyシーンの作成

今回の記事ではLobbyシーンを作成します。

ロビーとルームについては以下の記事を参照してください。

Lobbyシーン

まずはどのようなものを作成するかイメージを掴むために以下の動画をご覧ください。

今まではログイン画面からすぐにゲームルームに遷移していましたが、今回はログイン画面とゲーム画面の間に動画のようなLobbyシーンを作成します。

Lobbyシーンはプレイヤーが自分でルームを作成したり、ルームの一覧からルームを選んでゲームに参加したりできるようにするシーンです。

まずLobbyシーンのHierarchyビューを見てみましょう。

LobbyTitleTextには、「Lobby」という文字が入っていて、DisPlayInfoTextには、「部屋一覧」という文字が入っています。

ロビーシーンを構成する主な要素は以下の5つです。

  1. 部屋作成用パネル(CreateRoomPanel)
  2. 部屋一覧表示用パネル(RoomInfoPanel)
  3. 部屋一覧の要素パネルプレハブ(RoomElement)
  4. 部屋作成用パネルを管理するLobbyUI
  5. 部屋一覧の情報を取得するLobbyManager

これらそれぞれを1つずつ作成していきましょう。

部屋作成用パネル (CreateRoomPanel)

プレイヤーが部屋を作成する際に必要な情報を入力するウィンドウを作成します。

今回の部屋作成に必要な情報は部屋名と入室可能人数の2つとします。

以下の画像が部屋作成用パネルのHierarchyビュー上での構成とゲーム上での見え方となります。

  • CreateRoomPanelのTitleTextには「部屋作成ウインドウ」という文字が入る。
  • RoomNamePanelのTitleTextには「部屋名」という文字が入る。
  • PlayerNumberPanelのTitleTextには「人数」という文字が入る。
  • CreateRoomButtonのTitleTextには「部屋を作成」という文字が入る。

とりあえずここで気を付けるべきことはCreateRoomPanelの下に全ての要素があることです。

部屋作成ウィンドウの表示非表示操作を、親オブジェクトであるCreateRoomPanelのActive、InActiveによって実現するためです。

部屋の作成などの処理に関しては、後々作成するLobbyUIというオブジェクトのスクリプト内で行うのでここでは不要です。

つまりUIの外観さえ整えばOKです。

Panelを作る時の注意点

この構造では、CreateRoomPanelの上にRoomNamePanleが乗っていて、その上にPlayerNamberPanelが乗っているので、Panelで作る場合は、RoomNamePanleと PlayerNamberPanelのImageを無効にする必要があります。もしくは、PositionとScaleを調整して、被らない様にするか、 RoomNamePanleとPlayerNamberPanelとUIのPanleでなく、空のGameObjectを作成してもいいです。

部屋作成用パネル表示用ボタン (OpenRoomPanelButton)

OpenRoomPanelButtonは部屋作成用パネルの表示、非表示を切り替えるためのボタンです。

※ボタンを押した時の処理は、後々作成するLobbyUIのLobbyUIScriptの中で定義しています。

部屋一覧表示用パネル(RoomInfoPanel)とスクロールビュー

以下のような、ロビーにいる間存在する部屋の一覧を表示するパネルを作成します。

今回はとりあえず縦方向にしかスクロールできないビューにしているのでScroll Viewを作成した時に作られるScrollbar Horizontalは削除しています。

それ以外のオブジェクトの設定は以下の通りです。

Create/UI/Scroll Viewより新規作成した後、設定を変更した項目は赤枠で囲んでいます。

RoomScrollViewのInspector

今回、水平方向のスクロールは行わないのでHorizontal関連の設定は解除しています。

ContentのInspector(RoomScrollViewの孫オブジェクト)

AddComponentでVertical Layout GroupContent Size Fitterを追加します。

Vertical Layout Group縦方向に上手く要素を並べるためContent Size Fitter要素の大きさをうまく調節するため のコンポーネントです。

Scrollbar VerticalのInspector(RoomScrollViewの子オブジェクト)

部屋一覧の要素パネルプレハブ(RoomElement)

以下のような、部屋の一覧表示をする際に一覧の部屋それぞれの情報を表示するオブジェクトのプレハブを作成します。 このパネルは、スクリプトによって、Canvas→RoomInfoPanel→RoomScrollView→Contentに追加されます。

今回部屋一覧のオブジェクトに必要な要素は、以下の4つです。

  1. 部屋名…ルーム作成者が部屋につけた名前
  2. 人 数…ルームの最大入室可能人数
  3. 作成者…ルームの作成者の名前
  4. 入室用ボタン

これらのデータをインスタンス生成直後に読み込む必要があります。

RoomElementのInspector

Layout ElementはRoomElementプレハブの大きさを調節するためのコンポーネントです。

ここではこのオブジェクトの高さを50に設定しています。

CRoomElementScriptのRoomName、PlaerNumber、RoomCreaterには、RoomElement→RoomInfoPanelのRoomName、PlaerNumber、RoomCreaterテキストUIをアタッチします。

CRoomElementScript.csのソースコード

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;

public class CRoomElementScript: MonoBehaviour 
{
    //Room情報UI表示用
    public Text RoomName;   //部屋名
    public Text PlayerNumber;   //人数
    public Text RoomCreator;    //部屋作成者名
 
    //入室ボタンroomname格納用
    private string roomname;
 
    //GetRoomListからRoom情報をRoomElementにセットしていくための関数
    public void SetRoomInfo(string _RoomName,int _PlayerNumber,int _MaxPlayer,string _RoomCreator)
    {
        //入室ボタン用roomname取得
        roomname = _RoomName;
        RoomName.text ="部屋名:"+_RoomName;
        PlayerNumber.text ="人 数:" +_PlayerNumber+"/"+_MaxPlayer;
        RoomCreator.text = "作成者:"+_RoomCreator;
    }
 
    //入室ボタン処理
    public void OnJoinRoomButton()
    {
        //roomnameの部屋に入室
        PhotonNetwork.JoinRoom(roomname);
    }
}

部屋情報表示用テキストオブジェクトとして子オブジェクトであるRoomName、PlayerNumber、RoomCreatorを設定しています。

SetRoomInfoによるルーム情報の取得処理は、この後作成するLobbyManagerオブジェクトのLobbyManagerScript内で呼び出されます。すべての作業が終わったら、プレハブ化して、Resouceフォルダにいれておきましょう。

RoomButtonのInspector(RoomElementの子オブジェクト)

RoomButtonをクリックすることでその部屋に入ることができます。

ログインボタンのアイコン(EnterRoom_icon)はicooon_mono様から以下の素材を利用させていただきました。こちらからダウンロード

ダウンロードしたアイコンをEnterRoom_iconと名前を変更し、Texture TypeをSprite(2D and UI)を選択し、Apptyを押した後、SourceImageにアタッチする。

部屋作成用パネルを管理する LobbyUI

LobbyUIは先程作成した部屋作成用パネルの処理を管理するLobbyUIScriptを持ったオブジェクトです。

詳細はCLobbyUIScriptのソースコードLobbyUIのInspectorビューと設定をご覧ください。

CLobbyUIScript.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;

public class CLobbyUIScript : MonoBehaviour
{
    //部屋作成ウインドウ表示用ボタン
    public Button OpenRoomPanelButton;

    //部屋作成ウインドウ
    public GameObject CreateRoomPanel;  //部屋作成ウインドウ
    public Text RoomNameText;           //作成する部屋名
    public Slider PlayerNumberSlider;   //最大入室可能人数用Slider
    public Text PlayerNumberText;       //最大入室可能人数表示用Text
    public Button CreateRoomButton;     //部屋作成ボタン

    // Update is called once per frame
    void Update()
    {
        //部屋人数Sliderの値をTextに代入
        PlayerNumberText.text = PlayerNumberSlider.value.ToString();

    }

    //部屋作成ウインドウ表示用ボタンを押したときの処理
    public void OnClick_OpenRoomPanelButton()
    {
        //部屋作成ウインドウが表示していれば
        if (CreateRoomPanel.activeSelf)
        {
            //部屋作成ウインドウを非表示に
            CreateRoomPanel.SetActive(false);
        }
        else //そうでなければ
        {
            //部屋作成ウインドウを表示
            CreateRoomPanel.SetActive(true);
        }
    }

    //部屋作成ボタンを押したときの処理
    public void OnClick_CreateRoomButton()
    {
        //作成する部屋の設定
        RoomOptions roomOptions = new RoomOptions();
        roomOptions.IsVisible = true;   //ロビーで見える部屋にする
        roomOptions.IsOpen = true;      //他のプレイヤーの入室を許可する
        roomOptions.MaxPlayers = (byte)PlayerNumberSlider.value;    //入室可能人数を設定
        //ルームカスタムプロパティで部屋作成者を表示させるため、作成者の名前を格納
        roomOptions.CustomRoomProperties = new ExitGames.Client.Photon.Hashtable()
        {
            { "RoomCreator",PhotonNetwork.NickName }
        };

        //ロビーにカスタムプロパティの情報を表示させる
        roomOptions.CustomRoomPropertiesForLobby = new string[]
        {
            "RoomCreator",
        };
        // 部屋名がなければデフォルトの部屋名を設定
        if (string.IsNullOrEmpty(RoomNameText.text))
        {
            RoomNameText.text = "MyRoom";
        }
        //部屋作成
        PhotonNetwork.CreateRoom(RoomNameText.text, roomOptions, null);
    }
}

LobbyUIのInspectorビューと設定

上記の画像のように今まで作成したオブジェクトをドラッグ&ドロップで設定します。

部屋一覧の情報を取得する LobbyManager

LobbyManagerは部屋一覧の表示とプレイヤーのルーム入室時や作成時の処理を管理するLobbyManagerScriptをもつオブジェクトです。

詳細はLobbyManagerScriptのソースコードLobbyManagerのInspectorビューと設定をご覧 ください。

LobbyManagerScript.csのソースコード

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Hashtable = ExitGames.Client.Photon.Hashtable;
using Photon.Pun;
using Photon.Realtime;
using System.Collections.Generic;
using System.Linq;

namespace Com.MyCompany.MyGame
{
    public class CLobbyManagerScript : MonoBehaviourPunCallbacks
    {
        #region Public Variables
        //部屋一覧表示用オブジェクト
        public GameObject RoomParent;//ScrolViewのcontentオブジェクト
        public GameObject RoomElementPrefab;//部屋情報Prefab

        //ルーム接続情報表示用Text
        public Text InfoText;
        #endregion

        #region MonoBehaviour CallBacks
        void Awake()
        {
            //ルーム内のクライアントがMasterClientと同じシーンをロードするように設定
            PhotonNetwork.AutomaticallySyncScene = true;
        }

        #endregion

        #region Public Methods
        public void GetRooms(List<RoomInfo> roomInfo)
        {
            //ルームが無ければreturn
            if (roomInfo == null || roomInfo.Count == 0) return;

            //ルームがあればRoomElementでそれぞれのルーム情報を表示
            for (int i = 0; i < roomInfo.Count; i++)
            {
                Debug.Log(roomInfo[i].Name + " : " + roomInfo[i].Name + "–" + roomInfo[i].PlayerCount + " / " + roomInfo[i].MaxPlayers /*+ roomInfo[i].CustomProperties["roomCreator"].ToString()*/);

                //ルーム情報表示用RoomElementを生成
                GameObject RoomElement = GameObject.Instantiate(RoomElementPrefab);

                //RoomElementをcontentの子オブジェクトとしてセット    
                RoomElement.transform.SetParent(RoomParent.transform);
                //RoomElementにルーム情報をセット
                RoomElement.GetComponent<CRoomElementScript>().SetRoomInfo(roomInfo[i].Name, roomInfo[i].PlayerCount, roomInfo[i].MaxPlayers, roomInfo[i].CustomProperties["RoomCreator"].ToString());
            }
        }

        //RoomElementを一括削除
        public static void DestroyChildObject(Transform parent_trans)
        {
            for (int i = 0; i < parent_trans.childCount; ++i)
            {
                GameObject.Destroy(parent_trans.GetChild(i).gameObject);
            }
        }
        #endregion

        #region MonoBehaviourPunCallbacks

        //GetRoomListは一定時間ごとに更新され、その更新のタイミングで実行する処理
        // ルームリストに更新があった時
        public override void OnRoomListUpdate(List<RoomInfo> roomList)
        {
            Debug.Log("OnRoomListUpdate");
            DestroyChildObject(RoomParent.transform);   //RoomElementを削除
            GetRooms(roomList);
        }
        // マスターサーバーへの接続が成功した時に呼ばれるコールバック
        public override void OnConnectedToMaster()
        {
            PhotonNetwork.JoinLobby();
        }
        // ロビーに入った時の処理
        public override void OnJoinedLobby()
        {
            Debug.Log("OnJoinedLobby");
        }

        //ルームに入室時の処理
        public override void OnJoinedRoom()
        {
            //プレイヤーローカル変数初期化
            //LocalVariables.VariableReset();
        }
        //ルーム作成時の処理(作成者しか実行されない)
        public override void OnCreatedRoom()
        {
            //battleシーンへ遷移
            PhotonNetwork.LoadLevel("battle");
        }
        #endregion
    }
}

PUNでは PhotonNetwork.GetRoomList() でRoomInfoの情報を得る事ができましたが、PUN2ではGetRoomList()はないので、OnRoomListUpdateを使います。

以下に注意点が書いてあるので、余裕がある方は参考にしてください。

LobbyManagerのInspectorビューと設定

LobbyManagerは以下の画像のように設定します。

最後にログイン画面のシーンと繋げる

LauncherシーンのCLauncherScriptを以下のように変更する。

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Photon.Pun;
using Photon.Realtime;

public class CLauncherScript : MonoBehaviourPunCallbacks
{
    #region Public変数定義

    //Public変数の定義はココで

    #endregion

    #region Private変数
    //Private変数の定義はココで
    #endregion

    #region Public Methods
    //ログインボタンを押したときに実行される
    public void Connect()
    {
        //Photonに接続できていなければ
        if (!PhotonNetwork.IsConnected)
        {           
            PhotonNetwork.ConnectUsingSettings();   //Photonに接続する
            Debug.Log("Photonに接続しました。");
            if (string.IsNullOrEmpty(PhotonNetwork.NickName))
            {
                PhotonNetwork.NickName = "player" + Random.Range(1, 99999);
            }
            SceneManager.LoadScene("Lobby");
        }
    }
    #endregion

    void OnGUI()
    {
        //ログインの状態を画面上に出力
        GUILayout.Label(PhotonNetwork.NetworkClientState.ToString());
    }

}

実行結果

ログイン後、Lobbyシーンに遷移し、部屋一覧を取得できていますね!!

また自分で部屋も作成して入室することができました!!