PEOPLE
18.01.26
リポジトリサイズ20GBのbuildを効率化。DeNAの大規模ゲーム開発 改善班が挑んだ3つの壁

近年、多くのスマートフォンゲームは高品質かつ多機能になり、短いスパンで新しい機能やイベントをリリースし続けることが当たり前になっています。それに伴い、エンジニアをはじめとした開発メンバーが担当する作業の種類やソースコードの量は増え、負担も大きくなっています。それを改善するには、定期的に開発のムダや問題点を洗い出し、対策を考えることが重要です。
ゲーム・エンターテインメント事業本部 Japanリージョンゲーム事業部 第二開発部 技術第四グループの田辺 哲(たなべ さとる)は、部署が抱えていた大規模ゲーム開発の課題を解決すべく、有志で構成される「改善班」の一員として、開発効率化に“フルスイング”しました。彼らはいったいどんな取り組みをし、プロジェクトを成功に導いたのでしょうか。
目次
AssetBundle buildに時間がかり毎日QAを回せない
――改善班が結成された経緯を教えてください。
田辺:私たちの部署はかつて、ゲームイベントの運営のためチームメンバーが抱えているタスクの種類や量がとても多い状態だったんです。これをなんとしても変えなければと思い、改善班を立ち上げて抜本的に開発効率化を推進することにしました。
――タスクが多くなってしまっていたのはなぜ?
田辺:開発やbuildにかかる時間が増大しているからです。近年のスマートフォンゲームはゲームスキームも複雑ですし、グラフィックスも2Dから3Dになって高品質になり、開発規模も年々大きくなっています。
ゲーム・エンターテインメント事業本部 Japanリージョンゲーム事業部 第二開発部技術第四グループ 田辺哲
前職は SIer でミッションクリティカルな金融系システム開発に従事。 2011年にDeNAに入社し 、ngCore 立ち上げプロジェクトへの参画を経て、MobageSDK の開発などに従事。 現在は内製 3Dアクションバトルの開発に携わり、アクションバトルの開発からバックエンドシステムの最適化まで幅広く取り組んでいる。
さらに、お客さまに飽きないで遊び続けていただくために、複数のゲームイベントを週替わりでリリースしていく必要もあるんです。私たちが開発しているゲームですと、イベントを毎週3本ぐらい実施しています。さらに、キャラクターの衣装を変えたり、技の種類を増やしたりといった施策もやっているんです。そのため、Asset容量は大きくなり、buildにとても時間がかかっていました。
――具体的にはどれほどのファイルサイズなんですか?
田辺:プロジェクトのリポジトリのサイズは20GBくらいあり、ソースファイルは1万ファイルほどです。Assetファイル数はなんと7万ファイル近くもありました。
――想像もつかないくらいのファイルサイズですね……。
田辺:それくらいの規模になってくると、buildをまともにやったら1~2日は絶対にかかってしまうんです。そうなると、毎日QAを回すことが困難になり、品質を担保するのが難しくなってしまいます。開発を効率化し、その状況をなんとしても解決することが、改善班のミッションでした。
差分抽出により、AssetBundle buildを高速化
田辺:最初に手をつけたのは、AssetBundle buildに関する部分です。まずは、Jenkins Agentを複数ノードで運用できるようにしました。そのうえで、AndroidやiOSなどのプラットフォームやゲームイベントの案件ごとにノードを分け、分散・並列buildさせることにしたんです。Jenkins の Master / Slave 全体構成は次のイメージになります。
さらに、Unityプロジェクトは初回起動する際のAssetのImportに時間がかかります。なかでも特に、プラットフォームごとにTextureを圧縮する処理が重たいんです。そのため、ゲームイベントの案件ごとにUnityプロジェクトを再利用し、Asset Importの時間を削減できるようにしました。
加えて取り組んだのは、差分buildです。すべてのAssetファイルをbuildするから時間がかかってしまうので、Assetに変更があったものだけbuildする仕組みを構築することにしました。
――とはいえ、差分検出の仕組みをつくるのは大変なのでは?
田辺:そうですね。最初に試みたアプローチのひとつは、Assetが含まれる各フォルダのgit logを見て、フォルダの更新timestampから更新の有無を検知するアプローチでした。しかし、この方法ではうまくいかなかったんです。
――それはなぜ?
田辺:なぜかというと、特定のフォルダに含まれるAssetが、別のフォルダのAssetに依存しているケースがあるからです。その依存関係を考慮せずにtimestampのみで判断してしまうと、正しく差分を検出できませんでした。
――では、どんな方法で差分検出を実現したのですか?
田辺:Unityが公式に提供しているEditorUtility.CollectDependencies() というAPIを用いました。このAPIは、引数にAssetを渡すと、そのAssetが依存しているAssetのリストを返してくれます。これを用いることで、フォルダ内にあるAssetの依存情報を取得できるようになりました。そうしたうえで、実ファイルのMD5ハッシュを計算し、AssetBundle対象フォルダの配下に格納しておく仕組みにしたんです。
――なるほど。そうしておけば、MD5ハッシュに差分があったときだけbuildすればよくなるわけですね。
田辺:とはいえ、Asset容量が大きい大規模ゲーム開発では、MD5ハッシュの計算にも時間がかかります。そのため、複数プロセスで並列実行させることで、さらに効率化しています。
こういった複数の高速化を取り入れると、何も工夫しなければ1日ぐらいかかるようなAssetBundle buildも30分程度で完了するようになったんです。ちなみに、他のチームでもAssetBundle buildに2日ぐらい掛かり困っていたのですが、同じ仕組みを導入して、2時間程度で完了するようになりました。
バックエンドデータストアへのマイグレーション方式の最適化
田辺:さらに、バックエンドデータストアへのマイグレーション方式を最適化しました。
かつて、モバイルアプリケーションのバックエンドのデータストアはデータベースが主流でしたが、徐々にBaaS(Backend as a Service)に置き換わっています。BaaSを用いると開発効率は大幅に削減できますが、一方でデータマイグレーションをする際にこれまでとは異なるアプローチをとっていく必要があります。
初期の頃は、エンジニアが手動でデータストアへリリース用のデータをアップしていました。けれど、データ不整合などが原因でよく障害が発生していたんです。
――データ不整合が起きてしまう原因はどういったところにあるのでしょうか?
田辺:データベースへのマイグレーションは、歴史があるために手順が確立されています。更新用のスクリプトをStaging環境で流し、それが問題なかった場合に本番環境で同じものを流せば、おおむねマイグレーションが完了するんです。けれど、BaaSの場合はそういった手順が確立されていないですし、データAPIも公開されていないケースが多い。そのため、手動でオペレーションを行い、人的ミスが原因で障害が発生していました。
また、先ほども話したように週に3本くらいのイベントを開催していると、同時並列で10以上もの案件が同時開発されることになります。そのため、どうしてもソースコードや各種Assetのコンフリクトが発生してしまい、その解消に時間を取られることが多かったんです。
そうした状況を改善するため、データのマイグレーション方式を最適化し、各Assetのマージ戦略も整備していきました。
――具体的に、どうやってその状態を解消していきましたか?
田辺:前者のデータマイグレーション方式の最適化については、データストアへ反映するデータ(Master データやAssetBundle ファイル、WebViewコンテンツなど)をすべてgit repository で管理した上で、マイグレーションスクリプトを用いてデータストアへ反映する運用に変えました。
さらに、これらの作業はJenkinsを使って自動化するんですが、再実行が容易に行えるようJOBのインターフェースを最適化したんです。Jenkinsのビルド・パイプラインは極力シンプルにし、エラーが起きた箇所から容易に再実行できるよう、次のようなフェーズに分けてバックエンドデータストアに反映するようにしました。
――後者の「各Assetのマージ戦略」については何を実施しましたか?
田辺:コンフリクトが発生した場合に、自動的に解消できる部分と人間が介在して解消すべき部分を明確に分けました。そのうえで、自動的に解消できる部分はオートマージをし、そうでない部分は双方の担当者に通知したうえで解消してもらう運用を徹底したんです。
エンジニア以外もgitを活用
――他に、開発効率化のため実践したことはありますか?
田辺:デザイナーにもgitを使ってもらい、エンジニアへpull requestを送る運用に変えました。もともとはデザイナーが作成したAssetをエンジニアに受け渡してgitへpushする運用だったんですが、非常に効率が悪かったんです。
――とはいえ、非エンジニアのメンバーにgitを使ってもらうのは大変だったのでは?
田辺:そうですね。初期の頃はgitの使用方法について何度も同じ質問をされましたし、ときには危険なデータがpull requestされることもありました。
――その状況をどう解決しましたか?
田辺:デザイナーに対し「何回同じ質問をしても構わないので、不明なことがあればお気軽に聞いてください」というスタンスで向き合いました。それを続けていくと、どんどん彼らがgitの使い方を覚えてくれて。1年くらい経つとpull requestのマージそのものもデザイナーが実施するようになったんです。
――非エンジニアへのgit導入がうまくいったのはなぜでしょうか?
田辺:初期の頃に時間をかけて使い方を説明したのがよかったと思います。もちろん最初の数か月は説明に時間がかかりましたが、その後はエンジニアの作業が減らせたので、結果的には大きな工数削減に結びつきました。
また、SourcetreeのようなGUIツールがだいぶ進化してきており、直感的にgitが使えるようになっているので、そうしたツールを積極的に導入することもおすすめです。
良いアイデアを思いつくまで、粘り強く考え続ける
――それらの経験をふまえ、開発効率化のアイデアを思いつく秘訣を教えてください。
田辺:まずは、自分たちのチームが抱えている課題を「何としてでも乗り越えるべきものだ」という当事者意識を持つこと。そして、その意識を持ったうえで、解決策を毎日粘り強く考え続けることだと思います。そうすると、ある日突然パッと解決策が降ってくるんです。AssetBundle buildにEditorUtility.CollectDependencies()を使い差分で build することを思いついたときもそうでした。
どんな企業や組織でも、アプリ開発について大きな問題をいくつも抱えています。そうした問題は、1日や2日調査して対処できるものではなくて、ずっとウォッチし続けないとダメだと私は思っています。アイデアの種を温め続けておくといいますか。そうすることで、関連する情報を目にしたときに、「あ、これが使えるな」と発想できるんです。
すべての作業に対し、疑問と課題意識を持つ
――改善班の取り組みを通じて学んだことはありますか?
田辺:メンバーが苦労している作業は「何としてでも効率化・自動化する」という強い意思を持つことが大事だなと思いました。
先ほど話した非エンジニアのgit導入にしてみても、もしかしたら使用方法を誤ることでトラブルが発生する可能性もあったかもしれません。けれど、起きるかわからない問題をあれこれ考えてもしょうがない。それよりも、今起きている問題を解決することに全力を注ぐべきなんです。
もしアクションを起こしたことで問題が発生したなら、そのときに改めて解決策を考えればいい。トラブルを恐れて現状維持のままになってしまうのは、一番よくないと思います。
――最後に、大規模ゲーム開発に携わっている読者にメッセージをお願いします。
田辺:大規模なゲーム開発に携わるって、正直なところ大変な部分やつらい部分もあると思うんです。でも、その状況をしょうがないと諦めるのではなくて、乗り切るためにどうしたらいいか、どうすれれば自動化できるのか、無駄がなくなるのかを考えてみてください。疑問と課題意識を持ってすべての作業と向き合えば、きっと良いアイデアが生まれてくるのではないでしょうか。
まとめ
改善班が開発効率化にフルスイングできた秘訣
①差分抽出により、AssetBundle buildを高速化
②バックエンドデータストアへのマイグレーション方式の最適化
③エンジニア以外もgitを活用
④良いアイデアを思いつくまで、粘り強く考え続ける
DeNAの「色んなコト X 色んな技術」を知りたい方はコチラ!
田辺も登壇するDeNAの技術カンファレンス「DeNA TechCon 2018」は2月7日開催!
※本記事掲載の情報は、公開日時点のものです。
執筆:中薗昴 編集:野田竜平 撮影:小堀将生