FINAL FANTASY 
Record Keeper 
の作り方 
株式会社ディー・エヌ・エー 
Japan リージョン ゲーム事業本部 
新井 英資 eisuke.arai@dena.com 
©2014 SQUARE ENIX CO.,LTD / DeNA Co.,Ltd. All Rights Reserved.
自己紹介 
• 新井 英資 
• FINAL FANTASY Record Keeper (FFRK) 
リードエンジニア 
• 2011年入社 4年目 
• 以前はアルバイトでiOSアプリを作ったり 
• インフラやミドルウェアとチームを繋ぐ人 
• 出来ないことを出来るようにします
今日お話すること 
• FFRKというゲームを作ってみた話 
• FFRKのアーキテクチャの話 
• FFRKの運用周りの小話
FFRK というゲームを作ってみた話
FFRKについて 
• iOS/Android™向けにリリース(2014/09/25) 
• 株式会社スクウェア・エニックスとの共同開発タイトル 
• 全FFシリーズのバトルをドット絵で再現 
• 懐かしくて新しいFINAL FANTASY 
• システム開発はDeNA 
• おかげ様でとても好評
デモ 
• 実際の本番アプリの動画を再生します
開発当初の要件 
• アプリで作りたい 
– リッチなアニメーションを再生 
• コンテンツ更新をコントロールしたい 
– アプリ更新無しでのイベントリリース 
• これまでの既存リソースを使いたい 
– Kickmotor(D.O.T.、三国志ロワイヤル) 
– ブラウザゲー用の内製フレームワーク
ハイブリッドアプリ 
• WebViewレイヤとOpenGLレイヤの2層構造 
– リッチな表現はOpenGLで描画 
• WebViewBridge 
– WebView上のJSからネイティブの関数を実行 
WWeebbVViieeww 
OOppeennGGLL
ここはWebView
ここはOpenGL
WebView上のJS実装 
• MVCフレームワークの導入 
– フロントもきちんと構造化して実装 
• Backbone.js + RequireJS 
– 利用実績を考慮 
• Underscore template 
– JSTにコンパイルして使う
バトルの実装 
• FFのATBを再現するには… 
– 待機、詠唱、攻撃、などの状態制御 
• JSでステートマシンを実装 
– ネイティブアニメ描画とバトルロジックを分離 
• アニメーションはDeferredチェーン 
– ネイティブからの描画コールバックを待って次へ 
• ボス毎にステートマップを作成 
– 多彩なボスの行動制御
FFRKを作ったぞ! 
よしリリースだ!
リリース1ヶ月前の出来事 
• CBTの結果 
–重い 
–熱い 
• 10fpsを切るもっさりバトル 
• スクロール出来ないアイテムリスト 
• 充電しながらプレイしても電池が減る
orz
パフォチュー祭り 
WebView編 
• Chromeでのプロファイリング 
–無駄な処理を徹底的に洗い出す 
–レイアウト構造からの見直し 
• ネイティブと同等のレベルへ
これが
こう
これが
こう
パフォチュー祭り 
ネイティブ編 
• 各OpenGL描画APIのコールスタックを精査 
• 無駄な描画APIコールを減らす 
– 頂点数0での描画 
– 無駄に広い描画領域 
• 同じテクスチャを参照する描画をまとめる 
• Android2.X系でも30fps出るように 
– ドローコールは4分の1まで削減
これが
こう
ハイブリッドで作るメリット 
• イベントドリブンなゲーム運用が出来る 
– クライアント申請期間に左右されない 
– 究極的にはJSを変えれば全く別のゲームを作れる 
• ChromeやSafariでデバッグ出来る 
– ビルドをし直す必要が無くて便利
とはいえ 
• アクション性の高い要素は難しい 
– WebViewBridgeでのレイテンシ 
• 所詮はWebView 
– HTMLテンプレート読み込み途中で止まったり 
– ひっそりと再読み込みボタンを置く悲しみ 
• OSバージョンによる挙動の違い 
– 主にAndroid™ 
– 主にAndroid™
FFRK のアーキテクチャの話
ざっくり概要
クライアント構成
ネイティブアニメーション 
• アニメーションプレイヤー 
– 内製ツールで作成したアニメデータを 
 Cocos2d-xで再生する 
• 細かなアニメ制御 
– データでの制御 
– マスタでの制御 
– JSでの制御
ネイティブキャッシュ(図解) 
キキャャッッシシュュ機機構構 
デディィレレククトトリリ 
hhttttppdd 
ダダウウンンロローーダダ 
WebView 
持っていないアセットのみ 
をサーバからとってくる
ネイティブキャッシュ 
• WebViewからもネイティブからも透過的にアクセス 
– Mongoose を使いアプリ内部でプロキシサーバを立てる 
– http://127.0.0.1:12345/hoge?url=file&ver=abcde 
– キャッシュが無ければサーバから取得(cURL) 
• キャッシュさせるもの 
– 大体何でも 
• cssについては少し工夫 
– 保存時に画像URLを置換してキャッシュサーバを向ける 
• ビルドに抱き込むアセットも同様にアクセス可能
FFRKの運用周りの小話
高負荷対策 
• リリース後わりとすぐにTVCM開始 
– 急増するユーザ(現在:登録者数300万人超) 
– 荒ぶるWebサーバ 
• 迅速な負荷対応 
– シャードDBを追加投入 
– Webサーバを順次投入 
– 参照をslaveに逃がせる所は逃がす 
• サービス停止すること無く乗り切りました
マスタ管理 
• Google Spreadsheet で一括管理 
• Google Apps Script 
– マスタ間での値のマッピング 
– csvでの吐き出し 
• マスタ作成フロー 
– 開発環境でロード 
– マスタのテスト 
– Jenkins経由でgithub:EにPull-Request
ChatOps 
• IRC + Jenkins + Hubot 
– Jenkinsが失敗していると全員怒られる 
• Hubotが管理するもの 
– Jenkinsでのビルド状況 
– 検証環境の状態 
– その他余計な機能多数
まとめ 
• FFRKはハイブリッドアプリ 
– WebViewとネイティブの両レイヤで最適化 
• FFRKの特徴的機構 
– アニメーションプレイヤー 
– ネイティブキャッシュ 
• FFRKの運用は終わりなき改善の旅 
– 高負荷対応 
– マスタ管理 
– ChatOps
突然の謝辞 
• たくさんのエンジニアにご協力頂きました 
– インフラチームの皆さん 
– ミドルウェアチームの皆さん 
– パフォーマンスチューナーの皆さん 
– 開発チームの皆さん 
• ありがとうございました!!
ご静聴ありがとうございました

FINAL FANTASY Record Keeper の作り方

Editor's Notes

  • #21 ----- 会議メモ (2014/11/07 19:01) ----- CPUの処理時間も入れる
  • #31 ----- 会議メモ (2014/11/07 19:01) ----- mongoose