アマゾンバナーリンク

ディスプレイ広告

スポンサーリンク

PhotonCloudPUN2でシーンとルームの移動を実装する

2021年5月4日

こんにちは!ジェイです。今回はオンラインゲームでシーンとルームの移動の仕方を説明します。流れとしては、右クリックでシーンとルームの選択画面が出ます。この時に選択した後に、PhotonNetwork.LeaveRoom();で一旦ロビーにでてから、目的のシーンとルームに移動します。

記事内広告

最初のシーンのSampleSceneの構成

まず空のGameObjectを作って、CGameMain.csとPhotonViewをアタッチします。最初のシーンの名前はSampleSceneのままです。Connect Server→Create Roomすると何もない画面になりますので、右クリックでメニュー画面が出てきます。

CGameMain.cs

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

public class CGameMain : MonoBehaviourPunCallbacks
{
    private string roomName = "";

    Rect LobbyGuiRect = new Rect(0, 0, 300, 200);

    public static bool Menu = false;
    public static string SceneName = string.Empty;
    public static string RoomName = string.Empty;

    void Update()
    {
        ChangeCursorLockMenu();
        LobbyGuiRect.x = Screen.width / 4;
        LobbyGuiRect.y = Screen.height / 4;
        LobbyGuiRect.width = Screen.width / 2;
        LobbyGuiRect.height = Screen.height / 4;
    }

    // 接続したらロビーに入室する
    public override void OnConnectedToMaster()
    {
        PhotonNetwork.JoinLobby();
    }
    //GetRoomListは一定時間ごとに更新され、その更新のタイミングで実行する処理
    //ルームリストに更新があった時(ロビーに入ってるときのみ呼ばれる)
    public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {
        RoomList = roomList;
    }
    List<RoomInfo> RoomList = new List<RoomInfo>();
    void RoomNameUIWindow(int window_id)
    {
        // ルーム名の入力
        GUILayout.BeginHorizontal();
        GUILayout.Label("RoomName : ");
        roomName = GUILayout.TextField(roomName, GUILayout.Width(200));
        GUILayout.EndHorizontal();

        // ルームを作成して入室する
        if (GUILayout.Button("Create Room", GUILayout.Width(150)))
        {
            PhotonNetwork.CreateRoom(roomName);
        }

        // ルーム一覧を検索
        foreach (var room in RoomList)
        {
            // ルームパラメータの可視化
            System.String roomParam =
                System.String.Format(
                    "{0}({1}/{2})",
                    room.Name,
                    room.PlayerCount,
                    ((room.MaxPlayers == 0) ? "-" : room.MaxPlayers.ToString())
                );

            // ルームを選択して入室する
            if (GUILayout.Button("Enter Room : " + roomParam))
            {
                PhotonNetwork.JoinRoom(room.Name);
            }
        }
    }
    void PlayerNameUIWindow(int window_id)
    {
        // プレイヤー名の入力
        GUILayout.BeginHorizontal();
        GUILayout.Label("PlayerName : ");
        PhotonNetwork.NickName = GUILayout.TextField(
            (PhotonNetwork.NickName == null) ?
                "" :
                PhotonNetwork.NickName, GUILayout.Width(200));
        GUILayout.EndHorizontal();

        // MUNサーバに接続する
        if (GUILayout.Button("Connect Server", GUILayout.Width(150)))
        {
            PhotonNetwork.AutomaticallySyncScene = true;
            PhotonNetwork.ConnectUsingSettings();
        }
    }

    public static void ChangeCursorLockMenu()
    {
        // カーソルを外す
        if (Input.GetMouseButtonDown(1))
        {
            Menu = !Menu;
        }
    }
    public override void OnLeftRoom()
    {
        SceneManager.LoadScene("Lobby");
    }

    public static void DrawMenu()
    {
        if (Menu)
        {
            GUI.Box(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 140, 200, 300), "Menu");
            if (GUI.Button(new Rect(Screen.width / 2 - 80, Screen.height / 2 - 100, 160, 40), "MainGame1 RoomA"))
            {
                Menu = false;
                Cursor.visible = true;
                Cursor.lockState = CursorLockMode.None;
                SceneName = "MainGame1";
                RoomName = "RoomA";
                PhotonNetwork.LeaveRoom();
            }
            if (GUI.Button(new Rect(Screen.width / 2 - 80, Screen.height / 2 - 40, 160, 40), "MainGame2 RoomB"))
            {
                Menu = false;
                Cursor.visible = true;
                Cursor.lockState = CursorLockMode.None;
                SceneName = "MainGame2";
                RoomName = "RoomB";
                PhotonNetwork.LeaveRoom();
            }
            if (GUI.Button(new Rect(Screen.width / 2 - 80, Screen.height / 2 + 20, 160, 40), "MainGame3 RoomC"))
            {
                Menu = false;
                Cursor.visible = true;
                Cursor.lockState = CursorLockMode.None;
                SceneName = "MainGame3";
                RoomName = "RoomC";
                PhotonNetwork.LeaveRoom();
            }
            if (GUI.Button(new Rect(Screen.width / 2 - 80, Screen.height / 2 + 80, 160, 40), "MainGame4 RoomD"))
            {
                Menu = false;
                Cursor.visible = true;
                Cursor.lockState = CursorLockMode.None;
                SceneName = "MainGame4";
                RoomName = "RoomD";
                PhotonNetwork.LeaveRoom();
            }
        }
    }
    
    void OnGUI()
    {   
        // サーバに接続している場合
        if (PhotonNetwork.IsConnected)
        {    
            // ロビーに入室してる場合
            if(PhotonNetwork.InLobby)
            {
                // ルームに入室していない場合
                if (!PhotonNetwork.InRoom)
                {
                    GUILayout.Window(1, LobbyGuiRect, RoomNameUIWindow, "");
                }
            }
            else// ロビーに入室してない場合
            {
                // ルームに入室している場合
                if (PhotonNetwork.InRoom)
                {
                    DrawMenu();
                }
            }
        }
        // PUNサーバに接続していない場合
        else
        {
            GUILayout.Window(2, LobbyGuiRect, PlayerNameUIWindow, "");
        }
    }
}

Lobbyシーンの構成

次に移動するシーンの間のLobbyシーンを作ります。ここで空のGameObjectを作成して、CLobbyManager.csをアタッチします。

CLobbyManager.cs

メニューで選択して、ロビーに出るとまずOnConnectedToMasterが呼ばれて、JoinRoomで指定した部屋名の部屋がもしがあったら、その部屋に参加してなかったら、OnJoinRoomFailedが呼ばれるので、部屋を作成します。

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

public class CLobbyManager : MonoBehaviourPunCallbacks
{
    public override void OnConnectedToMaster()
    {
        Debug.Log("OnConnectedToMaster");
        PhotonNetwork.JoinRoom(CGameMain.RoomName);
    }
    public override void OnJoinRoomFailed(short returnCode, string message)
    {
        Debug.Log("OnJoinRoomFailed");
        PhotonNetwork.CreateRoom(CGameMain.RoomName, new RoomOptions(), TypedLobby.Default);  
    }
    public override void OnJoinedLobby()
    {
       Debug.Log("ロビーに入りました");    
    }
    public override void OnCreatedRoom()
    {
        Debug.Log("OnCreatedRoom");
        PhotonNetwork.LoadLevel(CGameMain.SceneName);
    }
    public override void OnJoinedRoom()
    {
        Debug.Log("OnJoinedRoom");
    }
}

MainGame1~4のシーンの構成

これも空のGameObjectにCSceneManager.csをアタッチして、シーンが区別できるように何か適当な物を配置します。それをMainGame1からMainGame4までの4つ作ります。

CSceneManager.cs

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

public class CSceneManager : MonoBehaviourPunCallbacks
{
    private void Update()
    {
        CGameMain.ChangeCursorLockMenu();
    }
    void OnGUI()
    {
        CGameMain.DrawMenu();
    }
   
    public override void OnLeftRoom()
    {
        SceneManager.LoadScene("Lobby");
    }
}

実行結果

Image from Gyazo

今回のアイコンはhalby24さんからお借りしました。

+2