【Unity】Photonを使ってネットワーク間同期
やっぱりゲームを作る上で通信は欠かせない。
サーバー借りるお金はないけど通信したい!っていう人にオススメなPhotonを使ってUnityで位置同期を目標に作ってみる。
Photonってなに?
Photonはさまざまなゲーム開発環境で使えるネットワークエンジンです
簡単に言うとオンラインゲームの通信機能をやってくれるやつ。
Photonの中にも種類があるのですが今回は簡単にできるPhoton Realtimeを使っていく。
Photon Realtimeはチャットやロビー機能、ルームの作成やマッチングなどが簡単に実装できる。
同時接続数20人までは無料!
登録とPUNのインポート
登録はここから。
登録が終わると、こんな画面になると思うので赤枠の所のアプリケーションID(AppId)をメモっておく。
ここからはUnityでの作業。
自分はUnity 5.2.1f1 Personalで行っています。
Asset Storeで「Photon Unity Networking Free」(PUN)をインポート。
インポートが終了するとPUN Setupウィンドウが出ると思うので、
そこに先ほどメモしたAppIdを入れる。
すでにUnityで表示されているかもしれないが、
Assets/Photon Unity Network/Resources/PhotonServerSettings を開き、
Inspector上からRegionをJpに変更し、Auto-Join Lobbyにチェックを入れる。
(それ以外だとラグが大きくなる)
Unityにはデモのシーンが出ていると思うが今回は触れないが簡単に2つのスクリプトの紹介。
RandomMatchmaker.cs -> ルームを作ったりマッチングしたりしてくれる。
(起動するとちょっとキモいキャラが出る。)
InRoomChat.cs -> チャットできる。
ルームの作成
まずルームを作らなきゃ始まらない!ってことでルームの作成。
とりあえずHierarchy上から右クリックしてCreat Emptyで空のオブジェクトを作る。
名前はPunManagerに。
次にPunManagerのInspectorからAdd Component -> New Scriptで新しいスクリプトを作成。名前はRoomMaking.csにしておく。
これだけでルームの作成は終了。簡単!
オブジェクトの同期するための設定
これだけだと通信してる感がない。
適当なオブジェクトを生成させて同期してみよう。
Hierarchy上から右クリックして3D Object->Cube でCubeを作成。
名前はCubeのままにしておく。
(本当はPlayerにしたかったがPlayerだと工事現場のおっさんが出てくる。)
ここからが重要でAdd Componentから
Photon ViewとPhoton Transform Viewを追加
下の画像のように設定する。Photon ViewのObserved Componentには、
Photon Transform Viewの名前の辺りをドラックアンドドロップして入れておく。
Photon Viewは同期させたいオブジェクトにアタッチする。これがないと同期しない。
Photon Transform Viewはその名の通りTransformを同期させるためにつけるのだが、
Interpolate Optionの欄でLerp(線形補間)を指定していることが重要で、これがないと同期ズレが激しくガクガクする。
こうして同期するオブジェクトを作り終わったら、
Project上からResourcesフォルダを作りそこに今作ったオブジェクトを入れる。
Resourcesフォルダだけはこの名前でないといけない。その理由は後で解説。
Cubeを動かすためのスクリプトを作る
この後Cubeを動かさないと検証できないので地面とCube動かすためのスクリプトを作る。本題ではないので簡単に説明する。
こんな感じで地面を作り、(全部白だと見にくいので赤くした)
Cubeを矢印キーで動かすためにこんな感じにしておく
これで再生してみるとCubeをごろごろ転がせる。
ここでCubeをHierarchy上から消しておこう。
同期するオブジェクトの生成
同期させるまで後ちょっと。
まずCubeにアタッチされているPlayerMoveのチェックを外す。
次に先ほど作成したRoomMaking.csを編集する。
ここで編集したのはOnJoinedRoom()の中だけだ。
普段オブジェクト生成させる際は
Instantiate(Object original, Vector3 position, Quaternion rotation);
こんな感じのInstantiateを使うが、今回はルームに入っている全員の画面に生成させなければいけないため
PhotonNetwork.Instantiate(string prefabName, Vector3 position, Quaternion rotation, int group);
を使う。
第一引数がプレハブの名前(string型)となっているが、これはResourceフォルダの中から探すことになっている。そのため生成させたいオブジェクトはResourceフォルダに入れなくてはならない。
その下の一行は先ほどのPlayerMoveのチェックを外したことにつながってくるが、
ここで自分のPlayerのPlayerMoveを有効(チェックを入れた状態)にしている。
こうしないとキー入力した際全てのPlayerが同時に動いてしまう。
実行
これで一通り終了。このシーンをセーブし(今回はtest.unityとした)、動かしてみる。
試すためには1度ビルドをして実行形式にする必要が有る。
File -> Build Settingsと進み、上のScenes In Buildにtest.unityだけがチェックされていることを確認しビルド。
こんな感じになりました。
左のウィンドウの時期は動いてるやつ、右のウィンドウの時期は真ん中で止まっているやつ。
まとめ
とても簡単に同期ができた。ほぼコードを書いていない。
ただ、やはりズレがあるなーって感じ。
Photon Transform ViewでSyncronize Rotationをやっていないので回転が同期されていないのが原因ではあるかも。
それを抜きにしても完全同期は無理がありそう。
でも、お手軽に作れて通信の挙動を確認できるからその点ではすごい!
ちなみにモバイル端末で利用するにはPhoton PUN+というPUNの有料版($95)じゃないといけないみたいです。
今回紹介した機能以外ではRPCって機能をよく使う。
またそれについて書くかもしれない。
今回作成したプロジェクトはGitHubに上げておいた。