naichi's lab

3日後の自分(他人)への書き置き

ゲーム投稿サイト「unityroom」に使われている技術

f:id:naichilab:20181210234000p:plain

こちらはCrieitで開催されている「個人開発サービスに用いられている技術 Advent Calendar 2018」14日目の記事です。昨日はnabettuさんの「cometsを支える技術」でした。cometsを使えば発表が楽しくなること間違い無しですね!

目次

はじめに

こんにちは、@naichilabです。Unity製のゲームを投稿できるサイト、「unityroom」を開発・運用しています。

f:id:naichilab:20181211213716g:plain:w320
unityroom

すべてのゲームが無料で、PCとWebブラウザさえあれば遊べます。
数多くのゲームが投稿されてますのでぜひ遊びに来てください。

このサイトは2016年4月29日に公開しました。あれから約2年半、おかげさまで公開されたゲームは3000を超え、非公開や限定公開も含めると4500を超える作品が投稿されています。

今日はアドベントカレンダーということで、このサービスにどのような技術が使われているかをご紹介したいと思います。

Ruby on Rails

Ruby on Railsは聞いたことある方も多いと思います。Ruby用のアプリケーションフレームワークです。分類的にはフルスタックフレームワークと呼ぶんでしょうか?大小様々なアプリが作れます。

unityroomもご多分に漏れず、大部分がRailsの標準機能で作られています。

なぜRails?

unityroomを作る前、前身として「うに部屋」(今はなきUnityWebPlayerの投稿サイト)を2年弱運用していました。そのサイトはPHPとCakePHPを使って作りました。CakePHPの入門書を手に取ってから二週間ぐらいでレンタルサーバーにデプロイできてしまい、あまりの手軽さに感動したのを今でも覚えています。

ただ、最初から最後までPHPが心から楽しいと思えませんでした。普段はC#ばかり使っていたので、PHPのゆるゆるな感じが馴染めなかったのかもしれません。(もちろん言語がダメというわけではなくなんとなく自分に合わなかっただけですよ!)

色々調べていくうちにRubyという言語やRuby on Railsというフレームワークがあることを知り、興味が湧いて次に何か作るときにはRailsを使ってみようと決めました。そしてRailsを勉強しながら最初に作ったサービスがこのunityroomです。

フロントエンド

f:id:naichilab:20181211182205p:plain:w320

フロント側を見てみましょう。

erb と slim

ビューテンプレートはRails標準のerbと、一部でslimを利用しています。 開発当初にslim良さそうじゃん〜と思って使い始めたものの、期間をあけて触ろうとすると構文調べることが多くて、結局シンプルなerbに戻そうとしていますw

CoffeeScript

スクリプトはRails標準のCoffeeScriptで書いてます。 CoffeeScriptで書いたものがRailsの機能でjsに変換されて出力されます。

Bootstrap4

CSSはBootstrap4を使っており、部分的に上書きしたりして使っています。

初期リリース時はBootstrap3 + 市販のテンプレート(買い切り$30)を使ってたんですが、市販テンプレートの機能が多すぎて素人の手には扱いきれませんでした。その後リニューアル時にすべて切り捨ててBoostrap4のみにしました。

ゲームのサムネイルが並んでいるのも全てBootstrapのCardsです。

Bootstrapは非デザイナでもとりあえずWebサイトっぽくしてくれるので好きです。

とはいえCSSゼロから書けるの憧れる〜〜〜。いずれはフルスクラッチでイケテルサイトを作ってみたいものです。

Vue.js

誰でもタグ編集画面だけVue.jsを使っています。

f:id:naichilab:20181211212626g:plain:w320

このページではvue-input-tagというライブラリを活用しています。

Vue自体とても分かりやすいですしもっと使いたいんですが、Railsとどう組み合わせていいか分からず横展開できてません。

Turbolinks(Railsの機能)はOFF

Rails標準機能にページ遷移を高速化するTurbolinksというものがあります。ページ遷移をフックすることで高速化する仕組みのようです。

しかしUnityWebGLのBGMがページ移動しても鳴り続けたりとよく分からない挙動をしたので安易にOFFにしました。(雑対応!!

バックエンド

f:id:naichilab:20181211221152p:plain:w320

続いてバックエンドです。

Heroku

ホスティングはHerokuを使っています。

リリース当初はConoHaのVPSにCentOSを入れて、Railsを入れて・・・ってやってたんですが、サーバー運用辛すぎてすぐに載せ換えました。多少出費はかさみますが時間を買ってると思えば安いもんです。

普段は Standard-1X dyno($25/月) 2つで運用しています。

f:id:naichilab:20181211221854g:plain:w320
スケールアップ・アウトの冗長構成とか自分じゃ組めないし組みたくもないです。覚える時間があったらサービス作りたい。

Heroku Postgres

データベースはHerokuアドインの Heroku Postgres ($9/月)を使っています。

これもちょっとお高いですがコマンド一行で定期バックアップの設定できたりと便利です。

Heroku Redis

Railsのキャッシュ保存先として、 Heroku Redis (無料)を使ってます。

Cloudflare

unityroom.com ドメインのDNSとして、またCDNとしてCloudflareを使っています。

f:id:naichilab:20181213225238p:plain:w320

無料で使ってますが、性能に不満を感じたことはないです。
認証とかあってもデフォルト設定でよしなにキャッシュしてくれてすごいなと思いますw

あとHerokuにホスティングすると標準ではネイキッドドメイン( www. のつかないドメイン)で公開できないんですが、CloudflareのCNAME Flatteningという機能を使うことで www. なしを実現しています。

ConoHa オブジェクトストレージ

日々増えていくゲームファイルの保存先として、ConoHa オブジェクトストレージを使っています。

クラウドストレージで一番有名なのはAWS S3だと思いますが、ゲームはファイルサイズが大きくなりやすく、データ転送量に課金されると財布が死んでしまいます。ConoHaのデータ転送量無料に惹かれて使い始めました。一年ぐらい前はアクセスが集中するとアップロードエラーが出たりしていたのですが、最近は大丈夫そう。サーバー補強されたのかな?

S3と同じくOpenStackという仕様に準拠してるそうなのでfogというライブラリを使ってAPIを呼び出しています。

今日確認したら122GB使われてました!
f:id:naichilab:20181211233335p:plain:w320

バッチ処理

定期的に実行する処理はRails内にRakeタスクを作成し、Herokuアドインの Heroku Schedulerで定期実行しています。

ちょっとした工夫

ファイル転送

ファイルアップロードはデータ転送量が多いので、Railsを介さないような工夫をしています。

  1. サーバー側でオブジェクトストレージのAPIを叩いてPUT可能な一時URLを取得
  2. 一時URLをクライアントに渡し、クライアントから直接オブジェクトストレージにアップロード

こうすることでRailsに負荷をかけずにアップロードすることができます。

前身の「うに部屋」ではPHPで作ったフォームでファイルをアップロードしていたので、ファイルサイズは100Mまで(Webサーバーの制限)、数人が同時にアップロードするとタイムアウトするなど、ひどい作りでした。

この辺りはどうしても解決したいと思い、unityroomの開発を始める前によく調べました。

ダウンロードもiframeでオブジェクトストレージに公開したコンテンツを読み込んでるだけなので、データはRailsを経由していません。

ランキングロジック

f:id:naichilab:20181211224952p:plain:w320

人気ランキングのスコア計算式についてはこの辺を参考に実装しています。

各社サービスのランキングアルゴリズムロジックの検討 - kenju's blog

PV、コメント数、評価数をベースに、時間で減衰するようにして入れ替わりやすくなるようにロジックを組み、定期的にスコアを再計算しています。

テストとか

テストはRSpecで書いています。とはいっても書き方よく分からず書ききれていないです。
投稿者以外からは見えないこと とか 何時何分に公開されること といった手動でテストしづらいものを重点的に書いています。

デプロイ方法とか

ソースコードはGitHubで管理しており、開発チケットはIssueで管理しています。

f:id:naichilab:20181211225535p:plain:w320

基本的にGithub Flowと呼ばれるブランチ運用をしており、チケット単位で開発(かなり適当)し、プルリクエストを作成しています。

プルリクエストが作成されるとHeroku Review Appsという仕組みで検証環境が自動デプロイされます。(プルリクエストがマージされるか閉じられると自動で消えます)

f:id:naichilab:20181211230039p:plain:w320

それと同時にCircle CIがテストを実行してくれます。

f:id:naichilab:20181211230338p:plain:w320

ReviewAppを使うことでマージ前に実際の動作を確認できるのでレビュー作業がとっても楽です。

プルリクエストがマージされ、masterブランチが更新されると、ステージング環境に自動デプロイされます。
この環境は常に起動しており、実際のファイルアップロードとかもできるようにしてあります。

f:id:naichilab:20181211231019p:plain:w320

ステージング環境で最終確認をしたのち、Heroku上でPromoteボタンを押すと、やっと本番リリースです!

本番リリース時もHerokuがDynoを順繰りに更新してくれるので、ユーザーから見てダウンタイムはありません。(データベースマイグレーションが必要な場合は止めますが。)

紹介したReviewApp、ステージング、プロダクションといったものはすべてHeroku Pipelineの機能です。簡単な設定でめっちゃ便利になるのでみんなにオススメしたいです。

監視

死活監視

死活監視は特にしてません。連絡受けたら自分で見に行きますw

パフォーマンス計測

管理者としてログインしている時だけrack-mini-profilerを表示するようにしています。

発行されたSQLの詳細とか、レンダリングにかかった時間とかが表示できます。

無料ですし簡単に使えるので重宝しています。

f:id:naichilab:20181211232643p:plain:w320

パフォーマンス計測その2

無料プランのNew Relicも入れてあります。

f:id:naichilab:20181211232954p:plain:w320

エラー発生時にどこのメソッドでどういうエラーが出てたかとか遡って確認できます。

無料だとスロークエリとか見れないのが難点ですが、そこは rack-mini-profiler で補ってます。

今後の目標

今はまだ 開発者が使う投稿サイト という感じなのでアクセス数も大したことありません。

これだけ多くのゲームを投稿してくれた開発者の皆さんに恩返しするためにも、 ゲームが遊べるサイト としてゲーム開発者以外のユーザーに使ってもらう必要があります!

機能追加や使い勝手の改善、デザイン改修などやりたいことは山ほどあるんですが全然作業時間が取れていません。

もしゲーム作りが好きでunityroomを一緒に開発したいぜ〜!みたいな人がいたらぜひお声がけください。 特にデザインできる人が手伝っていただけるとめっちゃ嬉しいです。(報酬は相談させてくださいね)

もっとアクセス増やして稼いで皆さんにどんどん還元したい!

まとめ

非常に長い記事になってしまいました。思い入れのあるサービスなのでまだまだ書けそうですがこの辺にしておきましょう。

naichiさんって本業はWeb屋さんですか?って結構聞かれるんですが、全然違うんです。 残念ながらゲーム作りもWeb開発も趣味でやっているので、全然時間が足りません。

とはいえ純粋に「楽しい!」を第一に考えて作れるのは趣味プログラミングのいいところですね。

ゲーム開発もWeb開発もですが、ああしよう、こうしようと考えたり話し合ったりするのはとても好きです。 なので意見・感想・要望などがあればドシドシお寄せください!!

みんな楽しく開発しましょう〜〜〜!

ここまでお読みいただきありがとうございました。それではまた!!

明日はSugiKentさんの記事です。お楽しみに〜