運営が立ち向かわなければならない2つの大原則とは? 長期運営を支えるエンジニアリング

ゲームとエンジニアの長寿の秘訣 #1/2 >> 2はこちら

ゲームエンジニアとして生き残るためのキャリア戦略

柿崎貴也氏(以下、柿崎):それでは、よろしくお願いします。柿崎と申します。今日は「ゲームとエンジニアの長寿の秘訣」ということで50分ほどお話しします。

最初に自己紹介します。柿崎貴也と申します。37歳でエンジニアをやっております。

愛知県出身で、名古屋大学を出たあとに、最初はヤマハという浜松にある楽器メーカーで組み込みのエンジニアをやっていました。ルータやカラオケなどの組み込みのファームウェアを10年ぐらいやって、そのあとアカツキというスマートフォンゲームを作る会社に4年半ほどいました。つい最近、昨年の11月からアダコテックというAIの会社にいて、サーバエンジニアをやっています。

今回は、主にアカツキにいた頃を思い返しながらお話ししたいと思います。1つのゲームで4年半ほど運用していまして、ゲーム自体はもうすぐ運用終了ぐらいな感じなのですが、スマートフォンゲームを長期運営するなかでどんなことを乗り越えていかなければいけないのか、なんとなくイメージがわかるとうれしいなと思っています。

ちなみに、ゲーム会社に勤めている方はどれくらいいらっしゃいますか?

(会場挙手)

なるほど。ゲーム会社じゃない人もいらっしゃると思いますが、それでもゲームに興味があって来ていただいていると思うので、おもしろくしていきたいと思います。

ソーシャルゲームの命運を左右する2つの大原則

ソーシャルゲームって終わるものもけっこうあると思うんですけど、今日のテーマはソーシャルゲームの長生きみたいなところです。

ソーシャルゲームって運営が始まってから終わってしまうまでにパターンがあって。最近では大規模開発になると開発の遅延が相次いで、「あれ、いつまでもリリースしないじゃん?」みたいなゲームもけっこうありますよね。

開発が長引くということは開発費がかかりすぎて、そもそも「黒字化ができない!」みたいな無理無理な感じのところから始まって、見切り発車でオープンしたものの、不具合を勃発してそのまま消えるみたいなゲームとか、そういうことがあります。

これはちょっと運用始まる前から終わっているので、そもそも全力でプロデューサーを止めに行ったほうがいいんじゃないかという話になってしまうので置いておいて、今日のテーマは、運用は始めてそれなりに売上は上がっているけれど、やはりじわじわ終わるみたいな、そういうパターンに絞ってお話をしたいと思います。

ソーシャルゲームを運用する上で絶対に逃れられない法則というのがありまして、それはこの2つです。

まず、当たり前ですが、収益が運用コストを上回るとそれが利益になるのですが、収益が運用コストを上回っていないとビジネスが成り立たないです。

1つ目の法則は当たり前っちゃ当たり前なんですが、2つ目の法則が重要で、運用コストって運営の時間経過とともにじわじわ増えていくんですよね。これはけっこう見落としがちです。

図にするとこんな感じです。

立ち上がって順調にいっているなと思うんですけど、収益にはけっこうばらつきがあって、上がったり下がったりを繰り返しながらやっていくんですが、運用コストは順調に上がっていって、このあたりを境に反転します。コストが収益を上回ってしまって「あ、やばいやばい!」って言いながらコスト削減を図ろうとするんだけど、それに収益の減少が追いつかなくて、そして終わる。

こういうのってけっこうあるんですよ。こういう終わり方をするゲームって多くて、コストの増大は運営している上で課題になります。

「売上の増やせば、それは解決するじゃん?」みたいな話があるんですけど、このへんの話は技術というよりはプロデューサーががんばったり広告を打ちましょうみたいな話になるので、そのあたりは今日は割愛します。今日は、地味なんですが、コストが増える話をします。

コストが増大する理由

なぜでコストが増えるかというと、例えば機能追加されてどんどんプロジェクトが膨れ上がるので、1個直すだけでもコストがどんどん増えていきます。また、スマートフォンゲームだと人がけっこう入れ替わるので、そのあたりのコミュニケーションコストが上がってしまって同じことをやるだけでもコストが上がってしまったり。あとは、最近はそもそも人件費が上がったりします。ですが実はスマートフォンゲーム特有の話で「神のお告げ」という物があるので、ちょっとその話をしたいなと思います。

まず、スマートフォンゲームには2人の神がいます。問題ですけど、これが誰かおわかりでしょうか? みなさん正解です。A神とG神という2人の神がいるんですね(笑)。

A神とG神は創造神でもあるんですけど破壊神でもあって、アプリに対して「アプリをアップデートするときはこれを守りなさい」という戒律を要求してきたりします。

とくにこちら側のA神はけっこう厳しくて、OSをどんどんアップデートしてくるんですけど、「iPhone Xを出したからこの解像度に対応してね」みたいな無理難題を押しつけてきたり、「iPadOSっていうのを出したから、対応してよね」とか、つい最近は「ダークモードにアプリが対応していないと、そもそも通しません」みたいな話があったりします。

そうすると、結果的にこうなります。

これ、メテオフォール型開発というらしいです。

こういう事もあって、スマートフォンアプリをアップデートするだけでいろんな新しい技術に追随していかなければいけません。

「じゃあ、アップデートとかしなければなんとかまったりいけるんじゃない?」とか「陰で破ってもそんなに被害はないんじゃない?」みたいなふうに思ってた時期がありました。2015年ぐらいまではそれほど厳しくなかったのでまったりしていた時期があったんですけど、とあるランキング上位のアプリがBanされるという事件が2015年の8月ぐらいにありました。

これをきっかけに「神には逆らうべからず」という不文律がスマートフォンゲーム業界で起きて、アプリを更新するときにはA社やG社が出しているガイドラインに基づかないと、そもそもアップデート申請が通らないし、そのうちアプリがストアから削除されちゃうみたいなリスクを背負うことになりました。

端末ID管理設計や64bit対応

ここでいくつか事例を上げて説明していきたいと思います。例えば、スマートフォンアプリはiPhoneやAndroidに端末IDという固有のIDをつかってアカウントを作ったりみたいな動作をしなきゃいけないんですが、古では、iPhoneならUDIDとか、AndroidはANDROID_IDみたいなものを取ってきて、それを固有IDとして使うという運用がまかり通っていました。

ですが最近はセキュリティ上の理由からANDROID_IDとUDIDは取れなくなっていて、既存アプリを別のかたちで作らなければいけなくなりました。これは技術力や工数が必要です。

OSのバージョンアップも先ほど言ったようなさまざまなフィーチャーがあるので、工数がかかります。

これはどうやるかというと、基本的にはAndroidやiOSの一次資料を当たって、それに基づいて実装をして、「こんなもんかな?」といってApp Storeで申請出して、跳ねられてみたいなことを繰り返す、そんな地道な作業です。

ゆっくりでもよければ、そのうちhow toがネットに上がるのでそれに乗っかってもいいんですけど、トップアプリを運用していると、なかなかそういうわけにはいきませんでした。

最近だとAndroidでは64bitのCPUに対応したバイナリじゃないと審査が通らないという話があったりして、そこでずっと32bitで動いていたアプリも64bitに対応しなければいけなくなりました。

ほかにも、サードパーティ製のSDKで昔は「F.O.X」というのを使ってたんですけど、いつの間にか「PartyTrack」と一緒になって、それがさらにAdjustに変わったり、クラッシュ追跡のSDKとして「Crashlytics」というものを使っていたらそれがTwitterに買収されて、それがさらにGoogleに買収されて、結果的にFirebaseにも対応しなきゃいけなかったり。あとはiPhone XやHTTPS、IPv6などに対応しなければいけないので、コストも上がってしまいます。

赤字に転落するとどうなるか?

赤字の話に戻りますが、ソシャゲの赤字ってつらくて、製造業みたいに3ヶ月に1回ボーンと商談がまとまって売上を達成したり、工場や土地といった資産を抱える商売ではないので、赤字に陥ると即刻開発費や運営費を削らなければいけなくなります。会社が大きければそれなりに保つんですが、小規模の会社だとすぐに経営難に陥って削らざるをえなくなるという結果に陥りがちです。

そうなったとき、ソシャゲの費用で一番多いのは人件費なので、人が減ります。そうするとアップデートが薄くなったり見る人もいなくなって不具合が連発したりして、さらにユーザーが離れて赤字が拡大するという悪循環になってしまうので、そこはやっぱり避けたいですよね。

僕的にやらなきゃいけないと思うのは、コストをコントロールすることかなと思います。運用年数とともに、なにもしないとコストがどんどん増えていってしまうので、それをどうやってなくしていくかが長期間運用をしていく上で大事なのでないかと思います。

とるべき手段としては2つ考えられます。

1つは開発に関わる無駄時間を減らすということ、もう1つは開発から運用ではいろいろなサイクルが回っていますが、そこでの手戻りを短くして、なるべくコストを幸せに減らしていくのがいいのではないかと思います。

開発の無駄時間を減らすというところでは、いろんな無駄な時間があるかなと思っています。例えばビルド時間やデプロイの時間、デバッグの時間はけっこう無駄というか、待ち時間が発生してしまうので、僕としてはそれぞれいろいろなことに取り組んできました。

ビルド時間を短縮する

まずはビルド時間の短縮です。これはアカツキで記事が出てたりするので、その話も見ていただければと思います。ここには書いていませんが、地味にビルド時間をけっこう短縮しています。

小さい字で書いてあるので読みにくいかもしれませんが、ビルドするときに、ネイティブのときはプリプロセスやヘッダを読み込むプロセスに長い時間がかかっていて、年数が経って肥大化していることもありますが、ビルドするだけで1時間ぐらいかかってました。でも、アプリが出てくるのに1時間待つのはけっこう辛いですし、無駄な作業があったりするので、これを減らすと開発の効率が上がりました。

このあたりはマニアックなんですが、まず、プリコンパイル済みヘッダを用意し、チューニングを施してプリプロセスにかかる時間を短縮しました。さらにAndroidアプリではndk-buildというMakeライクなビルドツールを使っていましたが、CMake(ninja)に変更して並列ビルドの効率がアップさせました。結果的には1時間ぐらいビルドにかかっていたのが20分ぐらいに削減したので、3分の1ぐらいに減りました。

また、最近トレンドですがCIを利用してGitHubにプッシュすると自動的にバイナリをビルドしてくれるみたいにしていました。これもけっこう重要で、とくにテストチームはビルド環境を持っていなかったりするので、そんなときに開発の人に「ビルドしてください」というのはけっこう手間ですし無駄な時間があるので、そういったものはCIを使ってサイクルを速くする、回りを良くするということは有効だと思います。

ほかにも、Cocos2d-xを最新版にするついでにいろんな向上をしたら、某掲示板で褒められたので、これはうれしかったので載せちゃいました。

テストを自動化する

あと、テストに関しても自動化に取り組みました。

ここに書いてありますが、クライアント側はCocos2d-xでC++で動いていて、cpplintとXCTestでテストを書いて実行しています。

プルリクエストが飛ぶたびにCircleCIで自動実行して、レビューの指摘事項は、reviewdogというツールを使ってコメントを打つようにしています。指摘事項を直してテストを通らないとマージしないようにしているので、一定の品質を担保するためにシステマティックになってます。

サーバ側も一緒で、サーバ側はRailsで動いているんですが、そこはRuboCopとRSpecをCircleCIで回して、そのコメントを直したりしてマージする感じで自動化をして、コスト増大をさせないような仕組みにしています。

次にデプロイ時間の短縮の話をします。

デプロイも年数を経ていくとどんどんテーブルの量が増えてくるので、時間がどんどんかかっていきます。ここはだいぶ古いテクノロジーなのでいまどき使うかどうかわかりませんが、テーブルごとにハッシュ値を求めて差分があるテーブルだけ更新するようにして、デプロイ時間を短縮したりしています。

最近トレンドなのはコンテナ運用かなと思っています。AWSでAMIからがんばって起動するのに比べると、コンテナはやっぱり相当速いですよね。

それと、デプロイに関しても、従来はSSHやrsyncを使ってデプロイしていましたが、それに比べるとコンテナを使ってデプロイすると速いですし、SSHやrsyncはネットワークでずっとつなげていなければいけないので、ネットワークが切れたらやばいみたいな不安に駆られるデプロイでしたが、それに比べるとコンテナは本当に安心して見ていられるので、アカツキとしてもコンテナ化を進めています。

ただ、僕が運用していたゲームでは、既存のものを置き換えるのが大変だったので、完全なコンテナ移行まではできていません。

開発環境もコンテナにしておくと、Dockerを入れてDocker Composeをやれば全部入るので、すごく楽になります。

手戻りを短くする工夫

開発サイクルの手戻りを短くするという話なんですけど、けっこうスマートフォンゲームの開発サイクル、設計して、実装して、検証して、リリースまで持ってくるのですが、そこでさらに運用というフェーズがあります。

けっこうあるあるなんですが、この開発部門と運用で、別に仲が悪いわけではないけれど、やはりなかなか見えない壁があって。例えば運用では何週間に1回のペースでキャンペーンをやるというサイクルを回していて、一方開発チームは1ヶ月とか2ヶ月かけてアップデートを実装していて、大抵のアプリではチームが分かれていたりするので、けっこうコミュニケーションロスが発生します。

もし運用でやってみたら「やっぱりこれは設計がまずかったね」となるとここまで手戻るので、そうなるとかなり致命的というか。また設計からやり直すと、1〜2ヶ月かけて開発することになってかなりつらい感じになるので、なるべくここの実装は検証の段階でバグを潰すのもそうですし、レベルデザインもがっつり作り込めるサイクルをできるかぎり回す仕組みが、スマートフォンゲームの運用には必要です。

そのため必要な技術は何かというと、レベルデザインをするときはマスターデータをポチポチいじってやるんですけど、そこをなるべく効率的にやらなければいけません。

マスターデータを一括で全部まとめて更新ではなくて、分割してなるべく小さい単位で更新してあげたりする必要があります。分割して更新をしたり、マスターデータに不整合が出ないようにバリデーションをかけなければいけません。

うちのチームの話でいうと、バリデーションコードはなるべくエンジニアが書きます。「こういうのがあると不整合になりますね」みたいなチェックコードをRubyでつらつら書いていって、それをプランナーさんができあがったマスターデータに対してSlackでコマンドを打つと、バリデータがもそもそ動いて結果をチャットで流して、エラーが出たらプランナーさんがエラーを潰すというサイクルを回すことで、なるべく前段階で弾いてあげて、レベルデザインがちゃんと動いた状態でリリースまで持っていくようにしています。

マスターデータの編集のやり方なんですが、スマートフォンゲーム業界はスプレッドシートやエクルでゴリゴリやるのが標準というか、事例が多いかなと思うんですけど、スプレッドシート運用は不整合を弾くのがけっこう大変なので、「専用のWebアプリを立ち上げてそこで入力すればしがらみもなく早く作れそうだし、バリデーションもそこで書ければ完璧なマスター管理アプリが作れるぞ!」と考えてやった事例もあります。

これに関して言うと、キャラクターのデータなどで部分的にうまくいくケースはありましたが、プランナーさんもスプレッドシートに慣れ親しんで、入力インターフェースとして「こっちで打ったほうが早い」という人もいたりして、マスター管理アプリでブラウザ上で打つのがいけるかというと、完璧に置き換えるまでには至らなくて、部分的にやってスプレッドシートと併用するみたいな、そんな感じになりました。

2Dから3Dになることで、アセット作成コストが増大

あとは、ゲームのトレンド的に2Dから3Dに移って、アセットを作る工数が劇的に増えています。

2Dだと、スプライトが、まぁパラパラ漫画のようにあって、エフェクトがあって、アニメーションがあって、エンジニアとプランナーが組み込むだけでだいたい動くのですが、3Dになるとモデルがあって、モデルにもローポリのモデルとハイポリのモデルがあって、それに対してテクスチャがあって、さらにマテリアルがあって、それがアニメーションして、さらにエフェクトがついて、照明とカメラがあって。それを全部バーンとインテグレーションしなければいけないとなると、まずここだけでも相当の工数がありますし、インテグレーションするのにいろんな要素が絡んでくるので、インテグレーションでも工数が増大するということになりがちです。

どう解決するかなんですが、僕はそれほど3Dが得意ではないということもありますし、それほどうまい解決策はまだ見られていないのが率直な感想です。自動生成みたいなのも試みられていますが全部が自動生成できるかというとそうでもないので、なかなか難しいですよね。

再利用可能コンポーネントを作るは1つのやり方かなと思いますが、現時点でどこまでいってるか、あまり事例がありません。

あとは、2D・3Dを組み合わせるやり方として、インゲームが3Dで、アウトゲームが2Dみたいなゲームはけっこう多いかなと。そういうところでゲーム的にバランスを取るというのが、いまのところ一番やれているやり方なのかなと思います。

ここまでの話をまとめると、長期運営するにはやはり黒字になってないとけっこうきついです。ただ、収益は技術力によって何かできるかという難しいので、技術力によってコストの増大を克服するのがいいんじゃないかなと思います。3Dの開発コストはどこも苦しんでいて、そこはエンジニアの飯の種にするといいかなと思います。

<続きは近日公開>