ura話スマートフォン用の表示で見るura話この広告は、90日以上更新していないブログに表示しています。2018-04-07🔥Firebase🔥でゲーム内に簡易SNSを作るカジュアルゲームを作っているときの「簡単な交流要素を入れたいけど、サーバーを運用するのはちょっと......」という要件にはmBaaSが便利です。この記事では先月リリースした「勇者、27歳、独身」の事例を元に、FirebaseでUnity製ゲームに簡易SNSを実現する方法を紹介します。ゲームは以下のリンクからダウンロードできます。勇者、27歳、独身は酒場にいる勇者の悩みを聞くゲームですが、カウンターの上にいる黒猫に話しかけるとプレイヤ自信の悩みを聞いてくれます。隣にいる白猫は他のプレイヤが投稿した悩みを持ってきてくれます。匿名でメッセージを投稿すると誰かしらが返信してくれる、いわゆるボトルメール系のサービスです。今晩の献立から人間関係まで、様々な悩みが投稿されています。類似サービスをいくつか参考にしたのですが、なるべく「気軽な気持ちで簡単に投稿できる」サービスにしようと思い、特に以下のような点を意識しました。会話が成立しないオンライン上で匿名の議論をすると大抵の場合荒れるので、そもそも言い合いが起こり得ないよう「悩みを相談して誰かが回答する」以降のやりとりをできなくしました。見返りが無い例えば「悩みに答えるとゲーム内のコインが貰える」といったこともできるのですが、あくまでコミュニケーション自体を楽しんでもらいため、そういった見返りは無くしました。履歴が残らない昨今の「twitterで過去の発言が引用されて炎上」や「Snapchatを始めとしたすぐ消える系のサービスが人気」といったニュースから、気軽なコミュニケーションにおいて過去の投稿が全て残る意味はさほど無いのではないかと仮定し、同時に投稿できる悩みを1つまでにしました。プレイヤの方からよく「履歴を見たい」「返信したい」といった要望をいただくのですが、とにかく気軽さを重要視しており、敵意や悪意を持って投稿するモチベーションをなるべく排除したいという意図があるので、これらの要望には応えられません。DBの選択では実装を紹介します。Database(以下rtdb)とFirestoreという選択肢があります。基本的にはFirestoreの方が新しいDBで、rtdbでは書けないような複雑なクエリを書くことができます。公式でも「β版であることを許容できるならFirestoreを使うべき」と書かれています。Firebaseですが、今回はUnityのSDKが提供されているrtdbを採用しました。FirestoreのUnitySDKは公式に提供されておらず(2018/04/05現在)自分で書くのは大変なのと、今回の要件ならrtdbでも充分こと足りるだろうという意図です。次にデータ構造を定義します。rtdbはRDBのようにテーブルやレコードといった概念は無く、1つの大きなJSONツリーでDB全体を表現します。今回は相談を表現する/postというトップレベルのノードを作り、/post/{userID}以下にユーザーごとの相談を作りました。}}上記の例ではtaroやhanakoといった文字列で表していますが、これはFirebaseAuth等で生成したユーザーごとにユニークな文字列を想定しています。各/post/{userID}以下には相談内容を表すquestion、回答を表すanswersがあります。1つの相談に複数の回答が付く場合があるためanswersは更に子ノードを持っています。ここに相談を書き込んでいきます。コードはこんな感じです。});}今回は「ユーザーが同時に投稿できる相談は1個」という制約があるため、新しく相談を投稿するときはsetで上書きしています。ユーザーごとに複数の相談を投稿できるようにする場合は、さらに/post/{userID}/{postID}のように一段深くネストさせてpushしていく感じになると思います。回答がついてない相談を探す相談に回答するときは、postの中から「まだあまり回答が集まっておらず、なるべく古い投稿」を探してきます。することで、どんな相談を投稿しても誰かしらからは返事が来る状況を実現しています。これは、全てのpostを1回答数昇順2投稿時間昇順でソートしてその先頭を表示させます。}}トップレベルに/postQueueを作ります。ソート用のフィールドを定義します(rtdbでは複数のフィールドでソートすることができないためソート用のフィールドが別途必要で、これは単に回答数と更新時刻をつなぎ合わせた値です)。検索する処理は以下のような感じです。});}ちなみに、これらソート用のフィールドは/post/{userID}に以下に直接定義してもいいのですが、やっぱり複数相談を投稿したくなって/post/{userID}/{postID}となった場合などはこのようにソート用のノードが必要です。rtdbでは特定のノード以下を一括して持ってくることしかできないため、post1つのデータ量が大きかった場合余計な転送が増えてしまうという点もあります。今回はどちらも問題では無いのですが、検索用のノードを別途作るというのはrtdbではよく使う手法です。indexも忘れずに定義しておきましょう。Functionsで処理を挟むさて後は回答に合わせてこの/postQueueを更新すればokです。今回のアプリでは回答待ちのpostのソート順は全ユーザー通して一定なので、複数のユーザーが同時に同じ質問に答える可能性があります。Functionsを使ってサーバー側で処理してみましょう。FunctionsはFirebase製品の1つで、サーバー側の処理を書けます。端末ごとに共通のロジックや、セキュリティ上の都合でクライアントに置きたくない処理を書くなどの用途に便利です。HTTPSでリクエストを投げて直接実行したり、ユーザーが登録したタイミングで実行したりできるのですが、今回はrtdbの書き込みを監視して実行するようにします。null})onUpdateは指定したパス以下を監視し、更新があれば実行されます。data.beforeから変更前のデータにアクセスできるのでこれを更新後のデータと比較し、差分があれば/postQueue/{userID}を更新します。push通知を送る最後に、回答が投稿されたらpush通知を送るようにします。これもFirebase製品のMessagingを使えば今までのコードと組み合わせて簡単に実現できます。tokenを取得してpostに付与しています。これで、/postのデータ構造は次のようになります。}}このtoken宛に通知を送れば、相談を投稿したユーザーに回答が届きます。先程Functionsで回答が投稿されたときの処理を書いたので、push通知を送るコードも書き加えましょう。null})sendToDeviceが実際に送信している処理です。Functionsでは非同期な処理の終了を待つ場合、promiseを返す必要があるので、先のpostQueue更新と合わせてallで返します。これで、端末側にpush通知が届きます。まとめという感じです。他にも、上記を組み合わせれば未読管理とその通知なども実装できます。Firebaseは他にもユーザー認証や静的webサイトのホスティングなど、ゲームを作ってるときに欲しくなるサービスが一通り揃っています。小規模であれば無料枠に収まる範囲で使えるので、是非一度導入してみてはいかがでしょうか。🔥Firebase🔥でゲーム内に簡易SNSを作るAppliv様にレビューしてもらいました1人でゲームを作ったとき助けてもらった素材集、2018春ブログ始めました月別アーカイブはてなブログをはじめよう!uraconさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。