【Unity】フレンドに見せられるお部屋機能を作ってみる【Firebase】

はいどーもこんばんは、もうすぐ無職のニートです。
本日はUnityとFirebaseを使って「フレンドに見せられるお部屋機能」を作ってみたいと思います。
要はオンライン通信機能のあるゲームでよく見られる「マイルーム機能」ですね。
これを今回は実装しちゃおうと、はい、そういうわけなんですね。

それなりに丁寧に一から説明していくので、よく詰まるであろう箇所、もとい僕が詰まった箇所へのフォローもしています。
Firebaseを使うのが初めての方でも多分問題なく読み進められますよ。

大前提

今回使うのは

・Unity(2017.3 0f3)
・Firebase(SDK 4.5.0)
・.Net 4.6
・Android(iOSは含まない)

となっています。

また、想定している読者は

・UnityからAndroidへのビルドができる環境をすでに構築している方
・C#の文法は一通り理解している(僕はC#6.0の書き方をよく使うので、C#6.0への理解もあると吉かも)
・Unityの入門書のサンプルを一つくらいは完成させたことがある
・uGUIもある程度は使える
・ただしFirebaseは一切使ったことがない

となっています。
とは言え「なんとなくしかわからんよ~」みたいな方でも全く問題ないです。
僕がそんな感じなので……。
ただコードの解説はほとんどしないので、プログラミングを始めたのが最近という方はちょっと苦しいかもしれません。

Firebaseってナンゾ

Firebaseというものを初めて聞いた方もいるかと思います。
かく言う僕もほんの一週間ほど前に存在を知ったレベルなのですが、これがなかなか面白い!
ごく簡単に言えば「オンライン通信機能のあるアプリを作るのに便利なツールを詰め合わせたもの」でしょう。
例えばデーターベースや認証システム、はたまたアナリティクスなんかまでできちゃいますよ。

ちなみにですが、今回使うのはデータベースのみです。
本当は認証システムも使ったほうがいい気がする……と言うか恐らくきちんとしたアプリなら使用は必須なのでしょうが、まだ僕が使い方をよくわかっていないので、今回は「誰でも読み書きできるデータベース」を使って「フレンドに見せられるお部屋機能」を作ろうと思いますよ(誰でも読み書きできるっていうのが最高に危なそうなので、テスト用以外ではちゃんと制限した方がいいと思います。僕もそのうち調べます)。

Unityプロジェクトの作成

何はともあれUnityのプロジェクトを作成しないといけませんね。
適当に新規作成したあと(僕は2Dプロジェクトを選びましたが、3Dでも問題ないです)、「File→Build Settings」からPlatformをAndroidに変えておきます。
ついでに、「File→Build Settings→Player Settings→Identification→Package Name」からここのパッケージ名を適切なものに変えておきます(ここで設定したパッケージ名はFirebaseのプロジェクト作成時に必要になります)。
また、ConfigurationからScripting Runtime Versionは4.6にしておいてください(僕がC#6.0のコードを書くことが多いため、こうしています。適宜書き換えられるなら別に古いバージョンでも問題ないと思います)。

中前提

さてUnity側の準備が整いました。
さっそく「マイルーム機能」を作っていきたいわけですが、先にFirebaseへの登録を済ませておきましょう。
もしあなたがすでにGoogleアカウントを持っているなら、
https://console.firebase.google.com/?hl=ja
このアドレスにアクセスして使用を開始するだけで大丈夫です。
Googleアカウントを持っていない方は作っちゃってください。

さて登録が済みましたら、Firebaseの新規プロジェクトを作成しなければなりません。
Firebaseの新規プロジェクト作成方法については以下のサイトが非常にわかりやすいです。
http://sleepnel.hatenablog.com/entry/2017/01/25/235100
上記のサイトに書かれてあることを簡単にまとめると

・プロジェクト名は何でもいい
・パッケージ名は「File→Build Settings→Player Settings→Identification→Package Name」と合わせる
・google-services.jsonを保存して、Assetsフォルダに放り込んどく
・Androidアプリを選択

ということですね。

これに加え、DatabaseからRealtime Databaseを作成してください(データベースの種類がもう一つありますが、今回は古い方のこちらを使います。たぶんUnityだと古い方しか使えない? かもしれません。よく調べてないので間違ってたらすみません)。
作成できたら、設定からルールをこんな感じに書き換えておいてください。

これはデータベースに対して誰でも読み書きOKという意味のようです。
基本的にはアクセス制限を加えておいたほうがよいようなので、テスト用環境でのみこの設定を使うようにしてください(この辺は僕も知識が全然ないので、そのうち勉強したいと思います)。
まあ確かに誰でもデータ書けまくったら不正し放題ですよね……。

小前提

Firebaseへの登録は済みましたね。
お次はUnityでFirebaseの機能を使うためのSDKを落としてきたいのですが、その前に少し説明があります。
エラーが出たとき適切に対処するためには必要となる知識なので、必ず目を通してください。

・日本語ユーザー名は使えない
FirebaseのSDKを使うとき、Windowsのユーザー名が日本語ユーザー名(2バイト文字)だとエラーが出ます。
なので、日本語ユーザー名で開発している人は別のユーザーを作る必要があります。
なおエラーが出るのはgoogle-services.jsonをAssetsフォルダに入れてからです。
Firebaseの機能を使うまではgoogle-services.jsonを抜いて開発をするのでもよいかもしれませんね(どっちにしろ日本語ユーザー名だと不便ですがw)。

・既知の問題が存在する
.Net4.6をFirebaseで使う場合、以下のサイトの「既知の問題」に目を通しておく必要があります。
https://firebase.google.com/docs/unity/setup?hl=ja
さらに、上記の「既知の問題」の設定を適切にした上で、async/awaitを使う場合は「Assets/Parse/Plugins/Unity.Tasks」を削除し、「Assets/Parse/Plugins/dotNet45/Unity.Tasks」のAny Platformにチェックを入れ、Excluded Platformsを全てOFFにする必要があります。
これをやっておかないと、async/awaitを使おうとするとエラーが出てしまいます。
async/awaitをガンガン使っている方はコレをやっておいた方がよいと思われます(僕はまだ非同期処理は勉強中の身なのであんまり関係なかったですけどw)。
なお公式サンプルコードはasync/awaitを使っていないので、それをそのまま使う場合は関係ないかなと思います(この記事ではasync/awaitを使わないので、この記事の通りに作っていくなら関係ないです。たぶん)。

SDKを導入する

さてもう下ごしらえはほぼ完了です。
最後にFirebaseのSDKを手に入れましょう。
https://firebase.google.com/docs/unity/setup
このページの「SDKをダウンロード」から入手できます。
僕が使用しているバージョンは4.5.0ですが、かなり頻繁にアップデートがあるようなので、バージョンが違っている可能性も大いにあります。
その辺はあんまり気にせず使っていきましょう(この記事を公開した日付は2018/4/18です)。

さてダウンロードしたら、解凍してください。
その後Unity側から「Assets→Import Package→Custom Package」を選択し、「FirebaseDatabase.unitypackage」をインポートしてください。
こちらがデータベース用のパッケージとなっています。

注*くどいようですが、.Net4.6を使用する場合はhttps://firebase.google.com/docs/unity/setup?hl=jaこのサイトと、Taskの設定を適切に変えてください。

これで準備完了ですよ。

お部屋の完成イメージ

フレンドにお部屋を見せるということは、そもそも「お部屋を作れる機能」がないと話にならんわけでして、これを簡単に作ってみましょう。
完成イメージは下図のような感じです。

人間と花の画像はいらすとやさんから借りています。

さて簡単な機能紹介です。

・ゲーム初回起動時にユニークIDを付加する(ユニークIDは利用者の区別に使用する。ユニークIDはローカルに保存しているが、Firebaseの認証機能を使うのも大いにアリ?)
・保存ボタンを押すと、現在のシーンの状態がFirebase上にJSON形式で保存される
・次回起動時はユニークIDを使ってFirebaseにデータを取りに行き、再現する(ローカルには保存しない)
・人間と花ボタンを押すと人間と花が生成される
・InputフィールドにフレンドのユニークIDを入れて「再現」ボタンを押すと、フレンドの部屋が再現される

上記の画像と説明を見てわかる通り、ここで作成するものは本当に簡単なものなので、実際にゲームを開発するときは皆さんで色々と工夫を凝らしてください。

とりあえず見た目を作成していく

画像のサイズは9:16を基準にして作成していきます。
適当にボタンとテキストボックス、ついでに「ユニークID」と書かれたテキストを設置していってください(uGUIを使っています)。
オブジェクトの名前はなんでもいいです。

次に人間ボタンと花ボタンを押した時に生成される画像を作成します(これはuGUIじゃないです)。
「ヒエラルキーを右クリック→2D Object→Sprite」で、人間の画像を設定してください(僕はいらすとやから借りましたが、なんでもいいです。サイズも適当に調整してください)。
同じように花オブジェクトも作ります。

その後、両方のオブジェクトにBox Collider2Dコンポーネントをアタッチします。
これはマウス(やタップ)でドラッグさせるときに必要となります。

あとは「Assets→Prefab」フォルダにプレハブとして放り込んだらOKです(フォルダは作成してください)。
このとき、人間プレハブの名前をPeopleに変えて、花プレハブの名前をFlowerにしておいてください。

オブジェクトを移動できるようにする

オブジェクトをドラッグやタップで移動させたい場合、以下のサイトにあるコードをまんまコピペでOKです(リンク切れてたらゴメンチャイ)。
http://neareal.com/1230/
uGUIのImageなんかで作成している場合はイベントトリガーやらPhysics2D Raycastみたいなの貼り付けたりしないといけないんですが、まあそれはまた別の話ということで。

さて上記のサイトのコードをコピペしたら、「Assets→Scripts」フォルダに放り込んでください。
できたコードを「人間プレハブ」と「花プレハブ」にアタッチしておきます。
ヒエラルキーに置いて、ゲームをテスト実行します。
人間と花がちゃんとドラッグで移動するかどうか確かめてください。

ユニークID生成機能を作る

お次はユニークIDを生成する機能を作成してみましょう。
クラス名はUniqueIdMakerとしておきます。
とりあえずコードをドン。

PlayerPrefsを利用してユニークIDを生成するコードです。
Firebase上に保存するのではなくローカルに作成しています。
必要があればこのユニークIDもFirebase上で管理できたら便利そうですね。
そのうちチャレンジしたいかも。
その他のコード内容についてはわりと丁寧にコメントを書いているので、解説を省略します。

さて上記のコードを、ユニークIDを表示するTextオブジェクトにアタッチしてください。
インスペクタのUniqueTextFieldにそのTextオブジェクト自身を登録しておきます。
実行してみて、ユニークIDが生成されていればOKです(何回か起動して、ちゃんと毎回同一のIDが生成されているかどうかチェックしてくださいね)。

人間と花を生成できるようにする

さてお次は人間ボタンと花ボタンから人間と花を生成できるようにしましょう。
ImageObjectCreater.csというファイルを作成し、中身は以下のような感じ。

ヒエラルキーを右クリックしてCreate Emptyをして、その空のオブジェクトに今しがた作ったコードをアタッチしてください。
また、作成済みの人間プレハブをPeople Prefabに、花プレハブをFlower Prefabに設定してください。

あとは人間ボタンと花ボタンのOnClickイベントにCreateFlowerメソッドとCreatePeopleメソッドを設定するだけです。
テストプレイしてみてください。
人間と花ボタンをクリックしたら人間と花が出てきましたか?
また、ドラッグで移動できますか?
できたら成功です。

データベースに保存するJSONデータを作成する

さて、ここまでで「自分のお部屋」を作成することができるようになりました(と言っても人間と花だけですけどw)。
ですが今の状態だと、一度ゲームを閉じたら「自分のお部屋」が消えてしまいますね。
これを起動時にきちんと復元しようと思います。

やり方としては「ローカルに保存したデータから復元」と「クラウドに保存したデータから復元」があると思うのですが、今回はもちろん後者を使います。
その前準備として、保存するべきデータをJSON化してみましょう。

注*実際のゲーム制作では「ローカルにも保存してクラウドにも保存」が最強だと思われます多分。

とりあえず今回は「位置」だけを復元したいと思うので、こんな感じ。
ImageObjectJson.csとしておきます。

ついでにリスト構造にしておきたいので、こんな感じのスクリプトも作成しておきます。

これでよーやく下準備が完了です。
次からFirebase関連のことをイジイジしていきますよ。

ImageObjectCreaterを改造していく

さてImageObjectCreater.csにFirebase関連の機能を追加していきましょう。
まずはデータベースのアドレスが必要になります。
と言ってもFirebaseのRealtime Databaseにアクセスして、トップの画面上部に表示されているアドレスをコピーするだけです。
https://XXXXXXXXXXXXXX.firebaseio.com/みたいなアドレスですね。
これがプログラム中で必要になるのでコピーしておいてください。

ではコードを一気にドン。

まずは_databaseUrlフィールドに先ほど取得したURLをペーストしておいてください。
それが終わったら、Unity側の各ボタンのOnClickイベントを設定していきましょう。
全てImageObjectCreater.cs内にあるコードです。

・読み込み→LoadFriendRoom
・保存→SaveMyRoom
・削除→ClearCurrentRoom

これでいったん動かしてみましょう。
まずは「自分のルームがクラウドに保存されているかどうか」をチェックします。

適当に部屋を作ったあと(人間と花を設置するだけですがw)、保存ボタンを押してください。
ゲームを終了し、もう一度起動します。
きちんと保存したデータが読み込まれましたか?
読み込まれたなら、成功です。

次はフレンドの部屋に行ってみましょう。
これが今回の目玉ですね。
と言っても我々開発者はボッチなので、フレンドも自分が兼任します。

先と同じように起動し、ユニークIDをメモしてください。
その後、ImageObjectCreater.cs内のStartメソッドの先頭にPlayerPrefs.DeleteAll();と書いてからゲームを実行し、いったんローカルデータを消去します。
次に起動するとローカルIDが変わっているはずです。
そこでテキストフィールドに先ほどメモしたユニークIDを入力し、読み込むボタンを押してください。
先ほど作ったルームが表示されれば成功です。

ゲームをいったん終了し、もう一度起動してみてください。
その状態で適当にルームを作り、保存しておきます。
そして先ほどと同じ手順でフレンドの部屋に行きます。
ちゃんと読み込まれたのを確認後、ゲームを終了し、また起動。
これで自分が今作った部屋が表示されましたか?
されたら成功です。
フレンドの部屋と自分の部屋が明確に区別され、JSONデータがFirebaseのデータベース上にあることがわかりますね!

一応Firebaseも確認してみましょう。
Realtime Databaseを開いて、データの項目を見ます。
すでに開いている状態の場合はブラウザの更新ボタンを押してください。
すると追加されたデータが二種類見えるはずです。
すなわち一つは最初に作成したデータ(フレンドとして使ったデータ)と、自分の現在のデータです。
「room-ユニークID」で区別されていることもわかるかなと思います。

実機での確認と改善点
さてここまでで

・ゲーム初回起動時にユニークIDを付加する(ユニークIDは利用者の区別に使用する。ユニークIDはローカルに保存しているが、Firebaseの認証機能を使うのも大いにアリ?)
・保存ボタンを押すと、現在のシーンの状態がFirebase上にJSON形式で保存される
・次回起動時はユニークIDを使ってFirebaseにデータを取りに行き、再現する(ローカルには保存しない)
・人間と花ボタンを押すと人間と花が生成される
・InputフィールドにフレンドのユニークIDを入れて「再現」ボタンを押すと、フレンドの部屋が再現される

を全て達成しました。
あとはビルドするだけです。
今回はAndroid向けの設定だけしかしていませんから(これは単に僕がiOS用の開発環境を持っていないというだけの話です。iOSを持っている人はiOSでもやってみてください)、Android用にビルドしてテストしてみましょう。
と言っても普通にビルドして、実機にapkファイルを入れるだけです。
実行してみてください。
エディタ上と全く同じように使用できていれば成功です(ただしデータベースからのデータ読み込みに時間がかかる場合がありますので、すぐに表示が切り替わらなくても焦らないでください)。
エディタ上とは別のユニークIDが付加されているはず(たまたま同じIDが付加された場合はドンマイ)なので、エディタ上のユニークIDを読み込んでみたり、逆にAndroid上のユニークIDをエディタ上で読み込んだりしてみてください
お部屋機能っぽいことができていますね。

さてここからは改善点を簡単に考えていきたいと思います。

・データベースのデータを参照するまでに時間がかかるときがあるので、「読み込み中」などとユーザーに表示した方が親切
・ユニークIDの生成方法
・データーベースへのアクセス権
・通信に失敗したときの処理
・存在しないユニークIDにアクセスしたときの処理

などなどがパッと思い浮かぶでしょうか(他にも色々あるかなと思いますがw)。
つまり今回作ったシステムをそのままゲーム内に流用するのはすっごい微妙ということですね。
僕はサーバーサイドのプログラミング知識が皆無なので、この辺はPHPとかを勉強してちょいちょい補強していきたいと思っています。

終わりに

いかがでしたでしょうか。
「Firebase使ったらマイルーム機能作れんじゃね?」と思ったので試しに作ってみました。
セキュリティの問題があるので別途勉強は必要そうですが、思ったよりも簡単にできて感動しています。
今参加しているチームの方が「オンライン対戦機能ならPhotonがいいよ」的なこともおっしゃっていたので、こっちも勉強してみたいなあなんて思っています。
ただまずはFirebaseを遊び倒したいので(ツクールMVでも使ってみて何かするかもw)、次は認証機能関連について調べてみようかなーと考えています。

ところで現在参加しているチームを今月いっぱいで辞めるのですが(二ヶ月間の社会人生活でした)、誰か僕を週3のバイト感覚で雇ってくれる人いませんかね……。
Unityで作ったゲームは現在参加しているチームで作った「ぬくぬく森の薬屋さん」だけですが、このゲームのプログラム部分はほぼ僕が一人でやってます。
また、ゲームの基盤となるADVシステムやら何やら(ぬくぬく森で使ってない機能、例えば選択肢機能とか色々)作ってました。
週3くらいで雇ってくれる人いたらツイッターでメッセージ欲しいです……。
(2018/04/18時点の話です)

リモートでの作業が嬉しいです(ぬくぬく森の制作もリモートでした)。
近場なら出勤も可能かもしれません(この辺はお互いに要相談な気がします)。
本気で探してるのでよろしくお願いします!

ほなそんな感じでまた。

フォローする