PUN2を学習する(1)

こちらのUdemyを視聴しつつハンズオンでPhoton(PUN2)を学んでいます.
※このコースはすべて英語です.
https://www.udemy.com/course/build-multiplayer-games-with-unity-and-photon-pun-2www.udemy.com

Photonとは

Photonはリアルタイムのマルチプレイ実装を提供してくれるプレットフォームです.
このUdemyコースではPUN(Photon Unity Networking)2を用いたゲームクローンを3つ実装できます.

この記事では最初のゲームクローンである"Pixel GUN 3D Clone"で,
マスターサーバーに入った後,ゲームサーバーに入るまでの実装の忘備録を記します.

初期設定

初期設定,マスターサーバーやゲームサーバーの用語の詳細についてはこちらが詳しいです.

PUN2で始めるオンラインゲーム開発入門【その1】 - Unity Connect

【Unity】PUNを使ってネットワーク同期処理をお手軽に実装する方法 -準備編-

スクリプト

PlayerNameInputManager.cs

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

public class PlayerNameInputManager : MonoBehaviour
{
    /// <summary>
    /// プレイヤー名を設定する
    /// </summary>
    /// <param name="playerName"></param>
    public void SetPlayerName(string playerName)
    {
        if (string.IsNullOrEmpty(playerName))
        {
            Debug.Log("player name is empty.");
            return;
        }
        PhotonNetwork.NickName = playerName;
    }
}

LaunchManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun; // PUNのコールバック関数を呼び出すのに必要  
using Photon.Realtime; // PUNのPlayerやRoomOptionsを呼ぶのに必要? またちゃんと理解してない

public class LaunchManager : MonoBehaviourPunCallbacks
{
    public GameObject EnterGamePanel;
    public GameObject ConnectionStatusPanel;
    public GameObject LobbyPanel;

    #region Unity Methods
    private void Awake()
    {
        // マスタークライアントのsceneと同じsceneを部屋に入室した人もロードする
        // マスタークライアントはルームを作ったクライアント
        PhotonNetwork.AutomaticallySyncScene = true;
    }

    void Start()
    {
        // 初期画面(ここでプレイヤー名を入力する)
        EnterGamePanel.SetActive(true);
        // 接続中の画面
        ConnectionStatusPanel.SetActive(false);
        // マスターサーバー(ロビー)に接続したときの画面
        LobbyPanel.SetActive(false);
    }
    #endregion

    #region Public Methods

    /// <summary>
    /// Photonサーバーに接続する
    /// </summary>
    public void ConnectToPhotonServer()
    {
        // Photonに接続されているかどうか
        if (!PhotonNetwork.IsConnected)
        {
            // PhotonServerSettingsに設定した内容を使って
            // マスターサーバーへ接続する
            PhotonNetwork.ConnectUsingSettings();
            ConnectionStatusPanel.SetActive(true);
            EnterGamePanel.SetActive(false);
        }
    }

    /// <summary>
    /// 入場可能なルームに入る
    /// </summary>
    public void JoinRandomRoom()
    {
        PhotonNetwork.JoinRandomRoom();
    }
    #endregion

    #region Photon CallBacks
    /// <summary>
    /// Photonに接続した時
    /// </summary>
    public override void OnConnected()
    {
        Debug.Log("Connected to Internet.");
    }

    /// <summary>
    /// マスターサーバーへ接続した時
    /// </summary>
    public override void OnConnectedToMaster()
    {
        Debug.Log(PhotonNetwork.NickName + " Connected to photon server.");
        LobbyPanel.SetActive(true);
        ConnectionStatusPanel.SetActive(false);
    }

    /// <summary>
    /// ルーム入場に失敗した時に呼ばれる
    /// </summary>
    /// <param name="returnCode"></param>
    /// <param name="message"></param>
    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        base.OnCreateRoomFailed(returnCode, message);
        Debug.Log(message);

        CreateAndJoinRoom();
    }

    /// <summary>
    /// ルームに参加したときのコールバック関数
    /// </summary>
    public override void OnJoinedRoom()
    {
        Debug.Log(PhotonNetwork.NickName + " joined to " + PhotonNetwork.CurrentRoom.Name);
        PhotonNetwork.LoadLevel("GameScene");
    }

    /// <summary>
    /// プレイヤーが入室した時のコールバック関数
    /// </summary>
    /// <param name="newPlayer"></param>
    public override void OnPlayerEnteredRoom(Player newPlayer)
    {
        Debug.Log(newPlayer.NickName + " joined to" + PhotonNetwork.CurrentRoom.Name + " " + PhotonNetwork.CurrentRoom.PlayerCount);
    }
    #endregion

    #region Private Method  
    /// <summary>
    /// ルームを作成する
    /// </summary>
    void CreateAndJoinRoom()
    {
        string randomRoomName = "Room " + Random.Range(0, 10000);
        RoomOptions roomOptions = new RoomOptions();
        roomOptions.IsOpen = true;
        roomOptions.IsVisible = true;
        roomOptions.MaxPlayers = 20;

        // ルームを作成する
        PhotonNetwork.CreateRoom(randomRoomName, roomOptions);
    }
    #endregion
}

PhotonServerSettingsはこれのこと.
AppIdRealtimeにはPhotonの初期設定の時のAppIdを貼り付けています.
ほぼデフォルト設定です.
f:id:xrdnk:20200113233118p:plain

流れとしては,
初期画面(EnterGamePanel)に名前を入力(SetPlayerName()が呼ばれる)

初期画面のボタンを押す(ConnectToPhotonServer()が呼ばれる)

Photon Serverへ接続する(OnConnected()が呼ばれる)

マスターサーバー(ロビー)に接続する(OnConnectedToMaster()が呼ばれる)

ロビーのボタンを押す(JoinRandomRoom()が呼ばれる)

ルームがないのでOnJoinRandomFailed()が呼ばれる

CreateAndJoinRoom()内のPhotonNetwork.CreateRoom()が呼ばれ,ルームが生成される

ルームに参加するとOnJoinedRoom()が呼ばれる

別のプレイヤーがルームに参加するとOnPlayerEnteredRoom()が呼ばれる

こんな感じかな.
Photonのコールバック関数についての一覧はこことかくわしい.
gamefbb.com

実際に動かす

一旦PhotonServerSettingsのEnable Support Loggerのチェックを外してます.
Build And Runで複数起動しています.マスタプレイヤーが入室→別プレイヤーが入室という流れです.
流れの通りにコンソール画面にログが出ています.

次は実際にマルチプレイまで実装してゲームクローン1を完成させるところまで.