うら干物書き

ゲームを作っています。

【Unity】僕もPhotonを使いたい #01 たくさんのConnect()

 オンラインマルチプレイゲームが作ってみたいなぁー……、と唐突に思ってきました。
 というのもUnityまとめにまとめられている情報の中に、ときおりPhotonの使い方をレクチャーしてくれているブログを見かけることがあります。
 Photon……、Unityと組み合わせることで簡単にオンラインマルチプレイゲームが作れるという話は以前からいろんなところで聞いていたのですが、なかなか手を出せずにいました。
 せっかくだからPhotonを使ってゲームを作ってみようではありませんか。
 Photonの内容のブログなんて何番煎じかわからないぐらいなので、味の薄ーい話になりそうですけど。


この記事にはUnity5.4.1f1及びPUN1.75を使用しています。

PUN

 Unityで使用するPhotonのAsset名は、Photon Unity Networking、略してPUNだそうです。
 ……これってなんて呼ぶんでしょうか。
 ピーユーエヌ、と呼ぶのか、パン、と呼ぶのでしょうか。
 ただパンだと少々混乱しそうですね。
 以前勉強会にて「パン使ってゲーム作らないんですか?」という話を聞かれたとき、食パンやコッペパンを使ったゲームについて尋ねられたのかと思ったぐらいです。
 そもそもオーディオ機能にもパンという固有名詞は使っていますから混乱してしまいそうですね。

 という雑談でした。

Assetをインポート、そして再生

 PUNをAssetStoreからダウンロード、そしてインポートしました。
https://www.assetstore.unity3d.com/jp/#!/content/1786

 インポートしたら、謎のウィンドウが立ち上がりました。
 どうやら何かしら設定する必要があるようなのですが、私は面倒くさいことは後回しにするタイプの人間なのでスキップします。

f:id:urahimono:20160913075554p:plain

 そしておもむろに何もないシーンで実行してみます。
 すると、当然のことながら怒られます。
 「設定しろよ!」と。

f:id:urahimono:20160913075606p:plain 

 この辺は設定は冒頭でお話しした通り、Unityまとめの情報からPhotonを使い始めていますから、先人の方々の知恵を拝借します。
 先行していろいろ調べてくれる人がいると助かるなぁー。
 私が参考にしたのは以下の方々の情報です。 tech.pjin.jp sleepnel.hatenablog.com

 PhotonのサイトでAppIDなるものゲットしてきました。
 これを設定してみましょう。

なんとなく繋げた気がする。ただ……

 手に入れたAppIDをPhotonServerSettingsというファイルに設定してあげる必要があります。
 場所はPhoton Unity Networking/Resourcesフォルダの中にPhotonServerSettingsはあります。
 直接Projectビューから探してもいいのですが、PUNをインポートした際に表示された謎のウィンドウからショートカットできます。えーと、どこにいったかなあのウィンドウ……。
 上部メニューのWindow > Photon Unity Networking > PUN Wizardから表示できます。
 ショートカットキーとして、「Alt + P」が割り当てられていますよ。
 そこからLocate PhotonServerSettingsを選べばPhotonServerSettingsのファイルがInspectorビューに表示されます。

f:id:urahimono:20160913075616p:plain f:id:urahimono:20160913075622p:plain

 えーと、先人の方々の知恵によると、Hosting設定をPhotonCloudにし、入手したAppIDをAppIdの項目に設定。
 Auto-Join Lobbyにチェックを入れ、あとはPhotonNetwork.ConnectUsingSettings()を呼べばOKっと。

using UnityEngine;

public class DemoNetwork : MonoBehaviour
{
    void Start()
    {
        PhotonNetwork.ConnectUsingSettings( null );
    }

    void OnJoinedLobby()
    {
        Debug.Log( "OnJoinedLobby()" );
    }

} // class DemoNetwork

 うん、OnJoinedLobby()内のログが表示されました。
 これでPhotonを使ってロビーに接続できたみたいなのですが、いくつか気になる点が。

 PhotonServerSettingsの項目にあるHostingの他の項目は何に使うのでしょうか。
 それにPhotonNetwork.ConnectUsingSettings()を記述した際に、他にもConnect関数の存在が確認できた気が……。

f:id:urahimono:20160913075635p:plain

 ちょっと調べてみましょうか。

いろいろあるよ、Connect()関数

 PhotonNetworkのクラスリファレンスを見てみましょう。 Photon Unity Networking: PhotonNetwork Class Reference

 ありますね。いろいろとConnect()関数が。

  • ConnectUsingSettings()
  • ConnectToMaster()
  • ConnectToBestCloudServer()
  • ConnectToRegion()

 ConnectUsingSettings()PhotonServerSettingsから情報を持ってくるのはなんとなく分かるのですが、他はどうなのでしょうか。
 PhotonServerSettingsHostingの項目の種類を見てみましょう。

  • NotSet
  • PhotonCloud
  • SelfHosted
  • OfflineMode
  • BestRegion

 いくつかConnect関数の内容と被ってそうなものがありますね。

ConnectToMaster()とSelfHosted

 一番わかりやすそうなConnectToMaster()SelfHostedから見てみましょう。

 bool ConnectToMaster( string masterServerAddress, int port, string appID, string gameVersion )

masterServerAddress サーバーのIPアドレス
port サーバーの接続ポート。
appID アプリケーションID
gameVersion このクライアントのバージョン番号

 Photonサーバーを自前でたてている場合に使う関数のようですね。

 ちなみにgameVersionには任意の文字列を指定することが出来、このgameVersionの文字列ごとにユーザーを分断することが出来るそうです。
 アプリのver1.0とver1.1は一緒に遊んでもいいけど、ver2.0とは一緒に遊ばないようにするときなどは、この文字列を変えてあげればいいみたいです。
 依然調べたInvoke()の時と違って、nullを指定してもエディタが爆発クラッシュしないようですね。

 Hosting項目のSelfHostedの設定画面を見てみましょう。

f:id:urahimono:20160913075649p:plain

 設定できるパラメータが、

  • Server Address
  • Server Port
  • Protocol
  • AppId

 と、ConnectToMaster()の設定パラメータと同じようなことから、ConnectToMaster()関数を呼ぶのと、SelfHosted設定をConnectUsingSettings()関数で呼ぶのとは同じ挙動であると推測できます。
 確認のためにConnectUsingSettings()関数の中を見たところ、処理内容はおなじゃものが記述されていました。
 ConnectToMaster()関数にはプロトコルの指定が出来ませんが、スクリプト内でプロトコルを指定するには、同じくPhotonNetworkクラス内のSwitchToProtocol()関数から指定するようです。
 今回はサーバーを自前でたてないため挙動の確認はとれない点が少し残念ですが。

ConnectToBestCloudServer()とBestRegion

 次に見てみるのは、ConnectToBestCloudServer()BestRegionです。
 これも同じような名前の関数と設定なのでConnectToMaster()SelfHosted同様、同じ挙動をするものではないかと推測できます。

 Hosting項目のBestRegionの設定画面を見てみましょう。

f:id:urahimono:20160913075659p:plain

 設定できるパラメータは以下の通りです。

  • Enabled Regions
  • AppId
  • Protocol

 BestRegionEnabled Regionsにて指定した地域の中で一番最適な地域につなげる方式のようです。

 ではConnectToBestCloudServer()にはどのような引数を指定すればよいのでしょうか。
 恐らくBestRegionに設定するパラメータと同じだと思いますが……

 bool ConnectToBestCloudServer ( string gameVersion )

 ( ゚д゚)ポカーン

 gameVersion一つしか引数が無ぇよ。
 BestRegionにあった調べる地域を指定するEnabled Regionsに相当する引数が無い!
 それより問題なのは、AppIDを指定する引数が無いことだ!
 AppIDは必須ではなかったかぃ?

 PhotonServerSettingsにAppIDを指定せずにConnectToBestCloudServer()を呼んでみましょう。

f:id:urahimono:20160913075709p:plain

Operation failed: OperationResponse 220: ReturnCode: 32767 (Empty application id). Parameters: {} Server: NameServer
The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account.

 怒られたじゃないか。
 いやいや、「アプリケーションIDが空だよ」と言われても、そもそもConnectToBestCloudServer()AppIDを指定出来ないじゃないか。
 ConnectToBestCloudServer()の中を調べてみましょう。

if (PhotonServerSettings == null)
{
    Debug.LogError("Can't connect: Loading settings failed. ServerSettings asset must be in any 'Resources' folder as: " + PhotonNetwork.serverSettingsAssetFile);
    return false;
}

if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode)
{
    return PhotonNetwork.ConnectUsingSettings(gameVersion);
}

networkingPeer.IsInitialConnect = true;
networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion);

 めっさPhotonServerSettingsから情報持ってきてるー……。

 そうなんです。ここが私の勘違いでした。
 PhotonServerSettingsファイルを参照しているのは、てっきりConnectUsingSettings()だけかと思っていました。
 そうではなく、AppIDの設定などはConnectToMaster()を除いて、全てのConnect関数でPhotonServerSettingsファイルから参照しているのです。
 ConnectUsingSettings()UsingSettingsの部分は、PhotonServerSettingsHosting項目に関して設定ファイルを参照するよという意味だったのですね。
 このことはConnectUsingSettings()の中を確認すればわかります。

if (PhotonServerSettings.HostType == ServerSettings.HostingOption.SelfHosted)
{
    networkingPeer.IsUsingNameServer = false;
    networkingPeer.MasterServerAddress = (PhotonServerSettings.ServerPort == 0) ? PhotonServerSettings.ServerAddress : PhotonServerSettings.ServerAddress + ":" + PhotonServerSettings.ServerPort;

    return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer);
}

if (PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion)
{
    return ConnectToBestCloudServer(gameVersion);
}

return networkingPeer.ConnectToRegionMaster(PhotonServerSettings.PreferredRegion);

 PhotonServerSettings.HostTypeによって呼ばれるConnect関数が分岐しているのが分かります。
 なるほど、PhotonServerSettingsファイルはちゃんと設定しなくちゃ駄目ですよ、ということなのですね。
 なまじ最初に調べたConnectToMaster()がスクリプトのみで設定できたため、他のConnect関数もスクリプトのみで設定できるものかと思っていました。

 そのため、ConnectToBestCloudServer()を使用する場合は、BestRegionのパラメータをちゃんと設定してあげる必要があります。

ConnectToRegion()とPhotonCloud

 最後にこの二つですね。
 ConnectUsingSettings()内で確認した通り、この関数とHostingタイプは同じ挙動になります。

 static bool ConnectToRegion(CloudRegionCode region, string gameVersion)

region 接続を指定する地域
gameVersion このクライアントのバージョン番号

f:id:urahimono:20160913075719p:plain

  • Region
  • AppId
  • Protocol

 BestRegionと違って指定した地域に直接接続するタイプですね。
 あっ、ConnectToBestCloudServer()と違ってConnectToRegion()は地域が関数側で指定できるんですね。

 ふぅ、オフラインモードを除いて、Connect関数の内容を網羅できました。
 最終的な結論としては、とりあえずConnectUsingSettings()を呼べばいいという、先人の方々がやってきた答えと同じものになりました。

 こんなペースではゲームが作れるのはいつになることやら……。

 次回 www.urablog.xyz