gracetory’s blog

東池袋にある合同会社グレストリのエンジニアブログです

初めてのPhoton(Unity2017.4.2) Part 1

f:id:grshizawa:20180511015717p:plain

まえがき

こんにちは、プログラマのshizawaです。
あーもう春かーと思っていたら、もう真夏が始まりますね。
前回からのブログから半年以上時間が経っていることに驚愕です。
(もっとブログを書こう・・・)

それでは
今回はUnityでネットワーク通信を使った対戦などに使用される「photon」というライブラリを使ってみようと思います。
初めて触る分野なので、初心者向けの内容になります。

photonとは

ネットワーク通信でマルチプレイを実現するSDKライブラリ。 マルチプラットフォームで利用が可能。 面倒な部分はAPI化されていて、簡単に実装ができるらしい。
そして、同時接続数が20人までであれば無料。

Unityのアセットストアからダウンロードして使う感じですね。

実行環境

・macOS Sierra
・Unity 2017.4.2
・Photon Unity Networking Free (ver 1.90)

前準備

長くなってしまいそうだったので、下記サイト様の内容を紹介します。 tech.pjin.jp (このサイト様には接続のためのNetworkスクリプトも参考にさせて頂いてます...)

ざっくりとした流れは
公式サイトにてアカウント作成
 ↓
アプリケーションを登録し、AppIDを取得
 ↓
Unityプロジェクト作成し、UnityのAsset StoreからPhoton(PUN)をダウンロード
 ↓
インポートしたら、設定ファイルに取得したAppIDを入力、各設定項目にチェック
 ↓
準備OK!

設定ファイルはこんな感じ(※AppIdの項目は取得したものを入力)
f:id:grshizawa:20180511174717p:plain

やりたいこと

チャットでやりとりするメッセージをニコニコ動画のコメントのように右から左に流れるようにしたい。

前知識

私がサイトを漁りながら実装するに当たり、最低限必要だったことを
参考にしたサイトを紹介しながら書いていきたいと思います。

PhotonNetworkクラス

公式サイトより
Photon Unity Networking: 基本説明

PUNは多数のファイルで構成されます。しかし重要なのはたった1つ: PhotonNetworkです。
このクラスは必要とされるすべての関数と変数を含んでいます。さらに独自の要件がある場合、
いつでもソースファイルを編集可能です。なにしろこのプラグインはPhotonの実装そのものなのですから。 Photonの機能はUnityの「PhotonNetwork」というクラスに集約されている。

この記事では、ルームに入室する、作成するなどの機能を持った
PhotonNetworkクラスの関数を利用しています。

イベント関数

サーバーへ接続が成功/失敗した時のタイミングで処理をするためには、イベント関数を使用します。 naichilab.blogspot.jp

例えば、ロビーに入った時のイベント関数は

OnJoinedLobby
/// マスターサーバー上のロビーに入った際に呼び出されます。
/// 部屋のリストが更新されるとOnReceivedRoomListUpdate()が呼び出されます。
/// 注意:PhotonNetwork.autoJoinLobby が false の場合、
/// OnConnectedToMaster() が呼び出され、部屋のリストが利用可能になることはありません。
/// ロビーに居る間、部屋のリストは自動的に一定間隔で更新されます。
/// (間隔はあなたが変更する事はできません。)
void OnJoinedLobby(){}

この関数をスクリプトに追加すれば、自動で関数内の処理を実行してくれます。

他プレイヤーとのマッチング

そもそもネットワークで通信すると言ってもどうやって他のプレイヤーと繋がるんだろう。。。
と、調べてみると
このサイト様の「LobbyとRoomについて」の項目がわかりやすかったです。 unity_photon_cloud_lobby_room_player - FreeStyleWiki

アプリでは、Playerが1つのLobbyに参加(Join)し、ここから用意された指定のRoomに参加(Join)、という流れをとります。 実際のゲーム処理は、Room内で行われます。 Roomに入っていないPlayerは、Lobbyに集まっている状態になります。 Roomが存在しない場合は新たにRoomを作り、そこにJoin。 Roomが存在する場合は、Roomを選んでそこにJoin。
(リンク先には図で書いてあるのでとても分かりやすい。)

Lobbyに通信を行うプレイヤーが集まり、どのプレイヤー同士がマッチングするか
決定したら、Roomを作成し入室をするということですね。

実践

まず必要なオブジェクトを全て用意

f:id:grshizawa:20180516150757p:plain

作成したのは下記オブジェクト
・GameManager (Create → Create Empty)
・Canvas (Create → UI → Canvas)
・InputField (Create → UI → InputField)
  入力フォーム
・Message (Create → UI → Text)
  右から流れてくるコメント
入力フィールドの位置は適当な位置で調整。

後に必要なので、CanvasにTagをつけておきます。
インスペクタのTagプルダウンから「Add Tag」をクリックして、「Canvas」タグを作成 f:id:grshizawa:20180511191417p:plain

ゲームビューはこんな感じ
f:id:grshizawa:20180511173001p:plain

他プレイヤーとマッチングするためのスクリプトを用意

Network.cs

using UnityEngine;
 
public class Network : MonoBehaviour {
 
    void Start() {
        // Photonサーバーに接続する(引数でゲームのバージョンを指定できる)
        // 前準備で設定ファイルのAuto-Join Lobbyをtrueにしていると、ここでそのままロビーに接続
        PhotonNetwork.ConnectUsingSettings(null);
    }
 
    // ロビーに接続すると呼ばれる
    void OnJoinedLobby() {
        Debug.Log("ロビーに入りました。");
 
        // ルームに入室する
        PhotonNetwork.JoinRandomRoom();
    }
 
    // ルームに入室すると呼ばれる
    void OnJoinedRoom() {
        Debug.Log("ルームへ入室しました。");
    }
 
    // ルームの入室に失敗すると呼ばれる
    void OnPhotonRandomJoinFailed() {
        Debug.Log("ルームの入室に失敗しました。");
 
        // ルームがないと入室に失敗するため、ルームがない場合は自分で作る
        PhotonNetwork.CreateRoom("myRoomName");
    }
}

Photonサーバー → ロビー → ルームと接続する最小限のスクリプトになります。
ロビーに接続後、すでに他プレイヤーがルームを作成していた場合はその部屋に入室します。
他プレイヤーがいない場合はルームの入室に失敗しますが、その後自分でルームを作成してから入室します。

このスクリプトをGameManagerにアタッチします。
f:id:grshizawa:20180511174017p:plain

この時点で一旦、実行。

f:id:grshizawa:20180511174336p:plain
画像のようにログが出力されていれば、成功です。
LogWarningが出ているのは、他プレイヤーがいないため、Roomの入室に失敗しているからです。

ここまでが他プレイヤーとのマッチングをするためのスクリプトです。

実際にマッチングしてみる

ひとつのパソコンでマルチプレイを検証するときは
「UnityEditor」、「Buildしたアプリ」の2つで行うのが手っ取り早いみたいです。

では今回はビルドしたアプリを実行した後に、Unityエディタ上で実行してみます。
f:id:grshizawa:20180514005857p:plain UnityEditor上のデバッグログを見てみると、先ほど実行した時は他プレイヤーが居らず、
Roomが存在しないためLogWarningが出ていましたが、今回はそれが出ていません。
すでにBuildしたアプリ側がRoomを作成していたので、UnityEditor側は作成されたRoomに入室した
ということになります。 これでマッチングして、同じRoomに入ることができました。

今回はここまで

続きはまた次回Part 2にて
次は実際にコメントを打って、同期をとる方法を書いていきたいと思います。