TechCon2017 - D-Stage01:その後のDeNAのネイティブアプリ開発(池田修)

2017年2月10日に開催された「TechCon2017」のなかで、ゲーム事業部 副事業本部長 池田修によるセッション「その後のDeNAのネイティブアプリ開発」が行われました。ネイティブアプリへ戦略的にシフトした背景をお話した昨年のセッションサマリに加えて、今年は具体的に課題となった点を技術的観点で深堀りしてお話しました。

トピックス一覧

1. 自己紹介
2. DeNAのゲーム開発の変遷
3. ネイティブアプリ開発の始動 ~敵を知り己を知れば百戦危うからず~
4. ネイティブアプリ開発環境と体制 ~どうやってゲームを作っているか~
5. ネイティブアプリ開発苦労話 ~失敗は成功の母~
6. Webサーバ vs ゲームサーバ

自己紹介

その後のDeNAのネイティブアプリ開発

こんにちは。
……こんにちは!(マイクを客席に向けて)

会場:(笑)

よろしくお願いします。池田と申します。

その後のDeNAのネイティブアプリ開発

「去年もこのイベント来たよ!」という方はいらっしゃいますか?

会場:まばらに挙手。

おお……。喜んでいいのかどうか、微妙なリターンレートでしたね(笑)。

会場:(笑)

去年の講演では我々DeNAが——それまでWebゲームで強かった会社が、ネイティブアプリを開発するに至った経緯や、どういう戦略を取ってきたかというご紹介をしました。
今年はその続きとしてお話させていただこうかなと思っています。

その後のDeNAのネイティブアプリ開発

僕はこのDeNAのゲーム事業部で色々やらせていただいているんですが、あまり外向けの活動はしていないので、ちょっとだけ自己紹介をさせてもらいます。

池田修と申します。
IT業界で40過ぎてると若干引かれることもあるんですけれど、まぁ、おっさんです。
エンジニアとしては、その昔、シャープがまだマニアが好きなパソコンを出していた時代に、Z80(ゼットハチマル)というCPUがありまして。中学生ぐらいの頃ですかね。パソコンを触り始めて、エンジニアリングが好きになりました。
職歴としては最初、フリーランスでコンソールゲーム開発等々を請け負っていて、その後、あるゲーム会社に入り、2011年にDeNAに転職してきて、エンジニアとしてやっています。
エンジニアなんですが、DeNAへ入って早々、「炎上しているタイトルのプロマネをやれ」とか、「組織を見ろ」という話があり……。
残念ながら、いまだにDeNAではそんなにコードを書けてないんですけど、という人間です(笑)。

その後のDeNAのネイティブアプリ開発

趣味はギターとか自転車。好きです。

その後のDeNAのネイティブアプリ開発

これ去年も紹介して——買ったばっかりで嬉しかったんでついつい載せちゃったんですけど、変なギターが好きなので、8弦ギターとかを買っていました。

その後のDeNAのネイティブアプリ開発

次はベースにも手を出して。音楽が結構好きで。
音楽に限らず、僕自身がゲーム作りが好きなのは、クリエイティビティある活動だっていうところなので、エンジニアリングでいろんな世界を自分の手で作り出せるというところが好きでやっています。

その後のDeNAのネイティブアプリ開発

ちなみに最近好きなギタリストはこの辺になっています。

その後のDeNAのネイティブアプリ開発

で、今日のお話について。
まずはDeNAのネイティブアプリの開発に関して、昨年の資料をベースにお話しようかな、と。
その後、昨年は本当にざざっと概要をお話しただけなので、課題になった点を技術的な観点でピックアップし、深掘りしていきたいな、と思います。
さらに、新たに継続している課題についても触れていきたいなと思っています。
対象となる人としては、アプリ開発に興味のある人、これから始めようとしている人、もう既に始めて結構苦戦している人。
とにかく「DeNAのゲーム開発に興味あるよ」というみなさまに楽しんでいただけたらいいかなと思っています。

それでは、昨年話したことのおさらいから。

DeNAのゲーム開発の変遷

その後のDeNAのネイティブアプリ開発

まず「そもそもDeNAという会社は、どんなゲームを作ってきたんだっけ?」というお話です。

その後のDeNAのネイティブアプリ開発

すごくざっくりになるのですが、こんな感じでゲームを作ってきています。
最初は本当に、ガラケーのブラウザゲームから始まりました。
で、しばらくしてシェアが大きくなってきたスマートフォンでもゲームを。
Kickmotorっていう、Webとアプリのハイブリッドのような、Webレイヤーとネイティブのレイヤーを重ねて描画するっていう仕組みを作ったりだとか……。
あとはブラウザゲームでも、シングルページアプリのような、ページ遷移を主体としないゲームを作ったりして。
これらを経て、2015年にパズル戦隊デナレンジャーというゲームをリリースしています。
あと、さきほども映像が流れていましたが戦魂ですね。

約5年間で、画面的にも進歩してきたかなと思っています。

その後のDeNAのネイティブアプリ開発

で、ここで一点お詫びです。
昨年来ていただいた方に指摘を受けたのですが……。
実はこの中に本当は『ngCore』というものがありまして。
若干名から「池田さんはngCoreを闇に葬りたいのか」とクレームを受けたんですけども(笑)。
こういう試みもしておりました。
結構チャレンジングな試みでした。
今は続いてないのですが、こういう試みも、今のネイティブアプリの開発には生きてるのかなと思っています。

その後のDeNAのネイティブアプリ開発

そして2016年。その後どうしているかというと。
「普通にネイティブアプリは作れるようになったかな」と思っているのですが、よりクオリティの高いものであるとか……最近だともう本当に、マルチプレイ要素だとか、3Dのアクションを制御するような、技術的にもチャレンジするようなアプリをリリースしています。

その後のDeNAのネイティブアプリ開発

ちなみに、スライド右上にTechCon2016とあるのは去年の資料の再掲なので、「去年も来たからこれ知ってるな」って方は、ちょっと手元で別の仕事をしていただいててもいいんですけども(笑)。

会場:(笑)

ネイティブアプリ開発の始動 ~敵を知り己を知れば百戦危うからず~

その後のDeNAのネイティブアプリ開発

もちろんいらっしゃってない方もいるので、ちょっとこの辺をおさらいしてみようと思います。

まずこれまでWebゲーム主体で、サーバーエンジニアが強い、運用力が非常にあると言われていたDeNAという会社が急に「ネイティブアプリを作ろう」となりました。
しかし、既にコンソールのプレイヤーが入り込んでいる非常に熾烈な市場に勝負していくというところで「これはきちんと戦略を立ててやらないといけないな」と思ったんですね。

その後のDeNAのネイティブアプリ開発

そこで最初に、我々は戦力分析をしました、と。
全部で150人くらいのエンジニアがいたのですが、全員を評価する形式で行いました。
まず「ゲームを作るのにこういうスキルが必要だよね」というのをざざっと挙げました。
一通りゲームを作ったことがある人なら、「まぁこういう仕事あるよね」ということですね。

その後のDeNAのネイティブアプリ開発

0ptはビギナーで、「全然やったことないです」という状態。
4ptはエキスパートです。「その分野では業界トップです」という状態。
「これで4pt付ける人はすごいなぁ」と思いましたが、実際付ける人は結構いたので、「きっと自信満々なんだなぁ」と思ったのですが……。
評価結果は残念ながら、68ptで満点中、平均4.8ptです。
全項目が0pt。「そもそもアプリ開発やったことないです」という人の割合も、75.7%でした。

これは感覚なのですが、大体、ゲーム業界でメインプログラマーを担う人というのは、結構なんでも出来ますというようなことが多くて。
当然、いわゆるメインプログラマー、リードプログラマーって、プロジェクトで技術的に何かあった時はケツを拭かなければならないので。
「そういう人なら68pt満点中、50ptくらいは自信持って付けてくれないとなぁ」って思っているのですが、そういうスタッフは3人ぐらいしかいなかったので、「これは結構大変だな」と思って、始めています。

その後のDeNAのネイティブアプリ開発

その次にですね。
さっき「熾烈な市場みたいだぞ」と思ったものの、他社がどれくらい技術力を要しているかみたいなのもちょっと調べておかないと、いつまでにどれぐらいの技術力で作れるようになったらいいのかという目星がつかないので、市場のアプリ——日本トップ50、アメリカでもトップ50ぐらいを、ざざっとピックアップして、とにかく技術的な観点で市場のアプリを評価する、ということをやりました。
当時まだまだ「アプリのガワを付けただけで中身はWebです」というタイトルもあれば、本当に「チャレンジでコンソール会社が出してきた」というタイトルもあり、すごく幅があったので、分け方としては、ひと目でhtmlと分かるような描画のWebベースアプリというのは、セグメント1にしました。
そして、「30fpsとか60fpsとかきちんと維持して、3Dも使ってるし、この挙動物理演算とかちゃんとやってんじゃないの?」というようなタイトルはセグメント5としました。
すると、ざざっとこんな感じのグラフが出来ました。

その後のDeNAのネイティブアプリ開発

結果、「こんなの難易度高くて手が出ないな」というようなタイトルは幸いにもごく一部でした。
アプリの収益を上げているタイトルというのは、「なんとか頑張れば作りきれるようになるんじゃないかなぁ」というところでやり始めています。
その後も、「我々が目指しているラインがさらに上がっていないだろうか」とか。
また、グローバルに展開していくにあたって、「海外では実はもっとレベルが高いんじゃないだろうか?」というところも気にしてやっていました。

当然のこととして、いろんな開発要素ががガラっと変わるので、「みんなはどんなところでひっかかるだろうか?」というのもある程度予測しておきました。

その後のDeNAのネイティブアプリ開発

大体僕がぱっと「みんながネイティブアプリ作るならわかってないと厳しいよ」って言ったのはこの4つぐらいでしたね。

プログラミングパラダイム。パラダイムが結構変わると思っています。
例えばWebでフロントとかGS系触ってる人は「非同期型プログラミングって難しいな」「どんなワークフレーム使えば楽になるんだろう」というような話はよくしていると思うんです。
どういうことかというと、ゲームというのはメインループがぐるぐる回っていて、その中できちんと非同期の制御を入れていくという作り方をしています。
ただ、Webサーバーの——要は特定のURLを叩かれた時に走るハンドラの中に処理を書くというのは逐次型の処理で大丈夫なので、「どういう風にコードを書いていいか」「設計していいか」というようなことがガラっと変わるというのが大きな変化なので、慣れないメンバーはいるんじゃないかなと思っていました。

次にマルチメディアデータ。
当然なんですが、今までWebブラウザゲームだったら、Webブラウザがグラフィックを出してくれたり、音も出してくれたりしていました。
でも、アプリでは自分たちで一定制御しなければいけませんし、どういう性質のデータなのかをわからないで使っていると、「知らぬ間にめちゃくちゃメモリ使ってました!」ということも発生してしまう。
そういうグラフィックとかサウンドのデータの取扱い——場合によっては描画のロジックから、という辺りは新しく覚えなくてはならないことかと思います。

あとはリソースマネジメントですね。
単純に、これはストレージスペースだとか、メモリだとかCPUだとかの話です。
Webゲームの場合は、サーバー分のリソースを全ユーザーが使うという構図になりますが、アプリの場合は、自分の端末のリソースを1ユーザーが使うということになります。
どちらもも考え方が難しいところはあるのですが、ガラッと変わる部分です。
Webサービスなどを運用したことある方ならわかると思うのですが、いざとなって、お金に権限を持っている人に泣きつけばサーバーを増やして一時的に凌ぐというようなこともできてしまうのですが、さすがにクライアントでメモリ不足の時にお客さんに「メモリ買ってください」とは言えないので(笑)。
この辺りの、リソースの上限というようなことをうまく意識するのは、結構重要かなと思っていましたね。

あとはもう、やはりチートというのは、サーバーサイドのマシンにユーザーはアクセス出来ないので比較的セキュアに保たれているのですが、クライアントというのは本当にあの手この手を駆使して、プログラムの中を見られるかもしれないですし、動いている最中のメモリ書き換えられてしまうかもしれないという、信頼できない環境で自分のコードが動くというようなことも、ガラッと変わるところなので、「事前にこういう風に作っていこうね」と戦略を立ててやっていきました。

具体的に、どういうような感じで進めていたかと言うと……。

ネイティブアプリ開発環境と体制 ~どうやってゲームを作っているか~

その後のDeNAのネイティブアプリ開発

ゲームを作る時は、普通、ゲームエンジンを選ぶものですが、DeNAでは2つのゲームエンジンを採用しています。
僕は組織を作ったり戦略を立てる上で、競争意識というか、比較対象がある環境が重要だなと思っていて。
1個だけでやっていると視野が狭くなったり、当たり前じゃないことを当たり前だと思って思考が止まってしまったりすることもあるので、2つのゲームエンジンでやるというのが良いと思っています。

その後のDeNAのネイティブアプリ開発

この2つはC+とC#なので、どちらかだけ得意という人がいると人材のアサインに困ったりもするのですが、とはいえ、きちんと2つ比べられる環境で開発を進めていくのが良いと思って2つ採用しています。

ひとつはおなじみUnity。3D系のゲームで利用しています。
もうひとつは内製のLiftEngineで、2Dのゲームで利用しています。
でもこちらは去年の内容で、今は、そろそろLiftEngineも3Dがいいんじゃないだろうかと、3Dまで対応する開発をしています。
この話はまた別のコマであるのかと思うので、このくらいにしておきます。

その後のDeNAのネイティブアプリ開発

あと、サーバーサイドですね。
これらは結構露出しているので、ご存知の方もいるかもしれませんが、Sakashoという内製のBaaSと言われるような仕組みを使っています。
ユーザー管理や決済、ゲーム内お知らせなど、「これはわざわざゲームチームがやらなくていいよね」ということは一手に引き受けています。
さらにゲームに特化した機能も多く用意していて、ガチャやログボなど「モバイルゲームだったら大体入ってるよね」という機能は網羅しAPIとして各タイトルに提供していて、場合によってはタイトルに特化して、ソーシャルゲーム時代お馴染みのレイドボスのような機能を入れたりなどもしています。

で、実はゲーム用のサーバーがもうひとつあります。
こちらはIRISというサーバーです。これは完全にマルチプレイ用に振り切ったサーバーです。
4人とか8人で対戦する時、クライアントが同じサーバーに接続して、パケットを仲介してマルチプレイのゲームができる。
そういうところを、いちいちゲームチームが開発せずとも実現し、安定して運用できる。
開発コストを気にしなくていい、という構造を作っています。

ネイティブアプリ開発苦労話 ~失敗は成功の母~

その後のDeNAのネイティブアプリ開発

で、さきほどお話したような下調べをして、技術的にも気をつけていこうという話をし、ゲームエンジン、サーバーはこういうのでいきましょうか、というので始めました。

その後のDeNAのネイティブアプリ開発

パラダイムの変化については、「ついていけない人が多いかもしれないなぁ」と思っていたのですが、中々理解できなかった人にその原因を聞いてなるほどなぁと思ったことがあります。
ゲームを作っていて「メインループから呼ばれる関数をガリガリ書いてます」というような人であれば想像がつくと思うのですが、ゲームプログラミングでは、自分のオブジェクトのステータスを変えつつ、何もしなくていい時はそのままリターンで返して、というような処理を書いていくわけです。
しかしここで、WebプログラミングにおけるFunctionなどを書いていた人にとっては、「関数が何もせずに返すというような概念をそもそも理解できなかった」と。
これは僕も聞いて「たしかにね」と思いました。
やはり思想が大分違うので、そこはうまく考えを変え、「ここはこういう作り方なんだね」と理解してもらうまで時間はかかりました。

次に、マルチメディアデータ。
大切なところは1回ミスって大体覚えてくれたんですけど、グラフィックとかサウンドのところは、若干クリエイティブなところも絡んでくるので、いわゆるゲーム業界でグラフィックス専門・サウンド専門にやっている人のレベルにはまだ至ってないなということで△にしています。

そして、リソースマネジメント。
ここはクライアントのリソースをしっかり使い切るという話ですね。
当然モバイルの場合は、Androidの下の方の端末って、ユーザーを多く取りたければなるべくサポートしたいので、限られたリソースでプログラムを動かしていくというのは考えてはいるものの、実際、開発終盤になって企画があれ入れたいこれ入れたいと言うと、うまく整理しきれずにずるずるパフォーマンスが下がっていって、最後2週間くらい「頑張ってパフォーマンスチューニングだ!」と言ってやるものの、どの端末でもサクサクだというのは最初の頃はなかなか実現できなかったなという感じです。

チートについては、結構対策できたかなと思っています。
これはもちろん完璧な対策というものはないのですが、DeNAのアプリゲーム事業が、クライアントアプリをやっている風になってきたなと思うのは、チートをする不正とのいたちごっこが起きていたりするところですね。
僕は、前職ではPCオンラインゲームなどをやっていたのですが、どんなに対策してもかいくぐってくる不正というのはあるので、そういうのはちょっと「クライアントアプリを作っている会社らしくなってきたな」と。
とは言え、きっと苦労するだろうとあらかじめ予想していた部分なので、それほど致命的な問題にはならなかったかな、と思っています。

ここまでが大体、去年お話した内容になります。
去年は「こういう問題がありました」というのをさらっとお話したので今年は「具体的にこの問題ってどういう風に起きたんだろう?」というのを話していければと思います。

コールバック vs ポーリング

その後のDeNAのネイティブアプリ開発

コールバック、ポーリングと書いてありますけれども。
複雑なステータス管理で、リソースの寿命が長い、すぐに消える、非同期で制御しなくちゃいけない要素がかなり増えた時に、何かしらのイベントを取る方法ですね。
なにかの処理の終了を検知して、別の処理を実行したい時、大体コールバックで処理する時と、ポーリングで処理する時があると思います。

その後のDeNAのネイティブアプリ開発

基本的なことですが、一応書いておくと。
コールバックは「該当処理が終わったらこの関数を呼んでね」と登録しておいて、その関数の中で必要な処理を行うというやり方です。
ポーリングは、該当処理が終わったかどうかを判定する関数が提供されているので、定期的にその関数をチェックして「終わったよ」となっていたら、自分で必要な処理を回す。
もしくは「そもそもの該当処理を駆動する関数自体が定期的に呼び出してください」という仕様になっていて「終わったら終わりましたと返します」というような形になっている場合もありますね。

その後のDeNAのネイティブアプリ開発

やっぱり我々、Web系の会社って、JSとかに慣れている人も多いので、イベントハンドラのように「コールバックで書いておけば、メインループの中にごちゃごちゃとめんどうな処理を入れなくていいよね」というように、比較的記述が簡単で馴染みやすいコールバックなのですが、いくつか——いや結構たくさん落とし穴があったかなと。
シンプルなシステムであればそれほど問題にはなりませんが、これはそれぞれ社内の開発で大きなトラブルに発展したばかりだったりします。
「コールバックが呼ばれると困るタイミングで、コールバックが呼ばれていました」というような問題です。
例えば、あるオブジェクトを生成し、そのオブジェクトが呼び出す処理の終了をコールバックで欲しかったのですが、運悪くゲームの進行によっては、コールバックが呼ばれた時には既にそのオブジェクトはなくなっている場合がある、というようなことに対応しなければいけないという話です。
あとは、「処理を2回並列で走らせたいんだけどなぁ」と思った時に「そもそもこのコールバックの仕様だと複数呼べないようになってますね」という話があったりとか。
もはや該当処理が不要になった時に止める手段だとか。

あとは、社内ではゲーム開発チームと、SakashoのSDKなどを作っている開発チームの複数があるのですが、「あいつらがコールバック呼んでないんじゃないか?」「あいつらコールバック2回呼んでるんじゃないか?」というように、若干チーム間で疑心暗鬼になって、なかなか取れないバグに対応したりだとか(笑)。
また社内で作っているものなら、なんだかんだ連携して作っていけるのですが、ミドルウェアなどを使っている時は「このコールバックってタイムアウトの時どういう挙動するのかな?」と思っても、今使っているものがブラックボックスだったりすると、「多分大丈夫だろうけど念のためコールバックが呼ばれなかった時のためにタイムアウトを入れておきたいな」だとか。
アプリの進行によっては早めにタイムアウト入れたい時、などにも対応しなくてはいけない、だとか。

で、クライアント開発の初期に、あまりマルチスレッドで書いたことがない人がハマりにハマったのが「コールバック呼ばれた時落ちるんだけど」「このスレッドから呼ばれたらダメなんじゃない?」という話でしたね。
コールバックは、簡単に使えて安全なケースもあるのですが、複雑なところで使うと結構大変なことになることがあります。
複雑な処理の中で、いろんなケースに対応しようとすると、結局コールバックをハンドリングするための実装がどんどん増えてしまって、「結局いろんなステータスを管理してポーリングと似たような感じになっちゃってるね」という。
コールバックを呼ぶ側、呼ばれる側というのも、いろんなことに対応しようとするので、対応策がどちらも同じことを慎重にケアしていたり、設計が複雑になったり、冗長になことやってるということになりがちなのです。
「個人的には」ですが、ループを回して非同期でがつっと組むようなものに関しては、最初からポーリングで組む方がいいんじゃないかなと思います。

その後のDeNAのネイティブアプリ開発

ここでまたよくあったのが「そもそも僕らが使ってるミドルウェアのインターフェースって全部コールバックで指定するんですよ」という場合。
で、その流れに乗ってずらずらコールバックで書いていくと、またトラブルが起きたりする。

その後のDeNAのネイティブアプリ開発

これは単純にインターフェースを変換すればいいだけかなと思ってます。
コールバック関数内では簡単なステータス変更だけ行い、そのステータスをポーリングするようなインターフェースに変換すれば、ミドルウェアがコールバックで提供していても、比較的薄い層でラップすることで、構造を変えることっていうのはできます。
そして大体、こういうトラブルが多いチームのソースコードを見ると、コールバック関数の中の記述が異常に長く、いろんな関数も呼んでいて、この関数がどこまでなんの処理をしているのかわからない、ということが多いです。
このコールバックが呼ばれた瞬間に「本当にこのリソースにアクセスしていいのかな?」というのが非常にわかりにくくなってしまうことが多いのです。
もしコールバック関数を書いていて、「いつの間にか肥大化してきたな」と思ったら、ちょっと注意したほうがいいんじゃないかな、と思っています。

RDBMS vs 構造体

その後のDeNAのネイティブアプリ開発

あともう1個起きた問題として。
我々は、サーバーエンジニアが多い会社からクライアントの実装を始めたのですが、コンソールをやってきた人もいました。
なにかデータ設計をしようとする時に、サーバーサイドをずっとやってきた人は大体、最終的にはデータベースを使うことが多くなるので、データベース的な設計を始めることが多いと思います。
仕事に慣れてくると、いちいちデータ構造だけを設計して、そこからER図に落とし、そこからクリエイトテーブル書いて、という段階ではなく、データ設計をしながら、テーブルもなんとなく思い浮かべて、「こういう排他処理とかロックとかしとかないと多分ダメなんだろうな」「これデッドロック起きちゃいそうだな」というのを一瞬で考えながらすぐにテーブル構造まで行き着いちゃうことが多いですよね。
やはりこういったことは、使うツールと設計思想が密着に紐付いてると思います。

一方、特にゲーム業界でガリガリゲームを作っている人というのは、CとかC++で書いているので、構造体とか——場合によってはクラスのメモリーイメージをそのまま思い浮かべながら、データ構造を定義することが多いですね。
僕もゲーム業界出身なので「構造体の中身ってどうやってメモリの中に置かれるのかな」と考えたりします。
ゲームに慣れてる人なら当たり前なのですが、例えば3バイトくらいのデータを確保した後には、明らかにアライメントなどで1バイト余るので、パディングとかリザーブとかを置いておかないと気持ちが悪くてしょうがない、というようなことは「あるある」だと思います。

その後のDeNAのネイティブアプリ開発

では、例えばキャラクターのパラメーターのデータ構造を設計してみようか、となると。
サーバーエンジニアの作るデータというのは当然、最終的にはクリエイトテーブルのようになります。

一方、構造体だと、こうです。

その後のDeNAのネイティブアプリ開発

見た目は、あまり変わらないんですね。

その後のDeNAのネイティブアプリ開発

ここから話が長くなってしまうことと、複数の要素が絡むので、ちょっとこの流れを覚えていただきつつ、Sakashoの話にもう一回戻します。

その後のDeNAのネイティブアプリ開発

Sakashoでは、データの取扱いに関して2系統の機能を提供しています。
我々DeNA社内ではよく、アセットとマスターと呼んでいるのですが、この使い分けはDeNAの方言のような気がしますので、今日覚えて帰って自慢げに話すと「それ何?」となってしまうかと思われるのでお気を付けください(笑)。

会場:(笑)

その後のDeNAのネイティブアプリ開発

で、我々がアセットとマスターという言葉をどう使い分けているのかと言うと。
アセットというのは、クライアントのストレージに永続的に記録されるデータです。
いわゆる、ゲームを立ち上げて「アップデートがあります」とダウンロードして、ストレージに保存するようなデータをアセットと呼んでいます。
大体はグラフィックやサウンド等々で、更新頻度は高くないけれどサイズが大きいのでしょっちゅうダウンロードはしたくないので、クライアントに保存しておきたいよねというデータ。
管理が大変なこともあり、ゲーム起動時に全てダウンロードする前提でやっていることが多いです。

そしてマスターというのは、クライアントのメモリ上で扱われ、都度ダウンロードされる類のデータです。
更新が頻繁だったり利用期間が限定されていて、いちいちストレージに書いたり消したりする必要のないデータです。
例えば長期間運用しているタイトルでは昔のクエストのデータが残っていたりするのはストレージの無駄なので、そういったデータは一時的に使うものとしてマスターを利用する場合があります。

双方が提供するAPIの機能としてはそれほど大きな違いはなく、単純に名前を指定しダウンロードするだけです。
ただ、用途の違いに合わせ、どうやって更新検知するのかなど管理機能が違ってくるくらいです。

その後のDeNAのネイティブアプリ開発

実際には、こういう図になると思います。
Sakashoは、クライアント側主導でアーキテクチャを考えられるようにするため、サーバーサイドではデータ管理機能については強力なものを持たずに、ファイルシステムがクラウドのサーバー上にもあって自由に使えるくらいのイメージで、汎用的な機能だけを提供していました。
マスターは直接メモリ上に行きますし、アセットは1回クライアント内のストレージに保存されてそこからを呼び出す、というよな構造になっています。
例えばマスターでクエスト配信をしましょうとなったら、クエストファイルのようなものにクエストデータを入れる仕組みにしておき、クエストをやろうという時に該当IDのデータをSakasho上からマスターとして拾ってくるというようなイメージで考えていました。

僕は、Sakasho初期の設計をこういうコンセプトでやっていました。
PCオンラインゲームをクライアント主導型で作った時に、作ったサーバーというのが、サーバーも複雑に絡んだアーキテクチャなんかを考えていくと、ゲームの調整とかをする時に結構ネックになってしまうことがあるので、ゲームの開発優先でしっかりおもしろいゲームを、ヘビーなクライアントを作っていくために、ゲーム開発チームがやりたいようにできるように、結構クライアントに寄せてやっていました。

その後のDeNAのネイティブアプリ開発

それでですね。
ここの主題であるデータベースの設計思想と、構造体の設計思想の違いですね。
我々、経験豊富なサーバーエンジニアがはじめてアプリを作った時に、実装したらこうなりました。
データベースというのは、大きな表から自由なデータを取ってくるという思想なので、多分これを作った人は、「大きな表がクライアント側にもあればいいんじゃなかろうか」と、巨大な表を起動時にマスターにどかんと持ってきてメモリ内においてそれをデータベースとして取り扱うという設計にしたんですね。

その後のDeNAのネイティブアプリ開発

ここでさきほどの話にもう一回戻ると、僕がなんとなく思っているテーブルのようなデータ定義と構造体は、こういったイメージで考えています。

その後のDeNAのネイティブアプリ開発

データテーブルは、やはり表だと思っていて、その表を自由に整形したり、データ取ったりするような機能というのが潤沢に用意されています。
それを使う環境としてはサーバーサイドで使うことが多いので、クライアントに比べるとメモリをたくさん使えるので、キャッシュしたり場合によってはまるごとメモリに載せて高速に使ったりもできます、と。
そして、クライアントからのアクセスを前提に作られているので、そこまで高速な処理は求められないというのがサーバーサイドのデータの扱いだと思っています。

その後のDeNAのネイティブアプリ開発

一方、構造体というのは配列にすることが多く、データの管理機能は限定的というか、自分たちで作る感じですね。
利用できるメモリは限られていますし、描画レートをきちんと維持しようとしたらブロッキングする処理にはできないので、とはいえデータアクセスを非同期でとなるとナンセンスなつくりになるので、高速にアクセスできるようなデータ形式にすることが多いかな、と。

大きな違いとしては、そもそもデータにプライマリキーが入らないことが多いかな、と思っています。
配列の添字でアクセスしてしまうので、構造体の中にはPK(primary key)が入らない。
このPKが入るか入らないかが思想の違いに繋がってるんじゃないかなと思っていて。
当然、PKが入るとPKで検索するんだろう、となるので、思想の違いがあったかなぁと思います。

その後のDeNAのネイティブアプリ開発

で、実際この実装なのですが。
クライアントサイドでもサーバーサイドと同じ感覚でアクセスできるのは良かったのですが、とにかくデータが大きくて、データの転送に時間がかかりゲームの起動も遅くメモリの消費量も激しい。
モバイル端末とインターネットの接続というのは、データセンター内のサーバーとデータベースほど高速には通信しませんし、クライアントはサーバーほどメモリも潤沢ではありません。
特にキャラの魅力で売っている長期運営型のゲームでは、運営が続くにつれどんどんキャラクターが増え、ゲーム要素が追加されるとパラメーターも増えてますので、このデータがどんどん肥大化していって、転送時間もメモリ消費もどんどん増加していく。
そしてある時、「このまま増え続けるとAndroidの一部端末ではメモリが足りなくなります」となりました。
「この構造を改修するか、低スペック端末を切るかどっちかです」というような話になってしまい、結構厳しかったです。

その後のDeNAのネイティブアプリ開発

また、こういう大きなデータを扱う時に、開発中結構メンテナンス性が低くてトラブルが起きていました。
マスターデータのメンテナンスについては、結構苦労している方もいると思いますが、これが実際、開発環境から本番環境へ移す際、大体はイベントが何本か回っているようなタイトルでは複数の開発者が同時にいじるので激しくコンフリクトします。
このコンフリクト解消職人がいないとリリースできません、みたいになるんです。

その後のDeNAのネイティブアプリ開発
その後のDeNAのネイティブアプリ開発

特にゲーム業界で、「効率の良い開発環境をつくりましょう」というようなことをやっている方なら、「プリプロセスでやりましょう」ということがよくあると思います。
これはどういうことかというと、個人個人は細切れのデータを管理して、途中で個人のデータをマージするツールなどを用意します。
弊社内だとこういうタイトルはなんとかコンフリクトをうまいこと解決してくれるマージツールを作って運用コストを下げていました。
そもそも全く別のファイルで作業しておき、そのファイルが結合されると、最終的に必要なものになりますよという風にしておけばいいかな、と。

その後のDeNAのネイティブアプリ開発

ここで、「どうやってその大きなデータの塊を扱わずに済むようにすればいいのか?」というのは重要な戦略だと思っています。
「配信してダウンロードするので、分割してくといいケースもあります」と。
「ただ開発中は作業者で分割しておいたほうが進みが早いことがあります」と。
よくある話として、キャラクターの名前とパラメーターが一緒に入ったひとつのファイルで作業している場合。
特にローカライズがあるタイトルとかはテキスト担当の人も忙しいので、「もうキャラクターの名前翻訳に回したいんで触っていいですか?」「ちょっと僕がまだパラメーター触ってるんであとにしてください」というような状況で、お互いコンセンサスをとらずにこっそり作業をしていたら、「僕の作業がめっちゃ巻き戻ったんですけど!」というようなことが起きたりだとか。

あとはデータの有効期限というのも重要だと思います。
例えば今週しか使わなくていいデータであれば、そんなに溜めておかなくていいですよね。
それはストレージ容量を圧迫しないように、転送量を増やさなくていいように、必要なところは切り捨てられるようにしておけばいいのかな、と。
ただ「全キャラのパラメーターを横並びで確認したいね」という時は、一覧性があった方が企画面では開発効率が良かったりもするので、そういう場合は一定リスクを取って分割しない、というパターンもあると思います。

なんとなくなんですが、最近のDeNAのゲーム開発では、作業者によって分割されたデータを作るものの、ダウンロード単位で扱えるようにパッケージしておく、と。
で、一覧性があった方が利便性が優るデータについてはまとめてしまう、みたいなハイブリッドなプランがトレンドになりつつあるかなと思ってます。
つまり、全てランタイムで処理しなくちゃいけないみたいに思ってる人もいるかもしれないんですけど、プリプロセスで処理していくということ、あらかじめ処理していくことというも結構有効だと言う話です。

その後のDeNAのネイティブアプリ開発

ただですね。
この話って、若干、オジさん的だと思っています。
なぜなら僕がプログラムを書いていた頃は、メモリは節約!節約!で、メモリを先輩と奪い合うという世界で。

その後のDeNAのネイティブアプリ開発

今モバイル端末はスペックの進化が著しいので、下手したらマシンパワーやメモリが余り気味になってしまうかもしれないので、それをゲーム体験に振るか開発効率に振るかは一定バランス考えてやればいいところなのかな、と思ってます。

Webサーバ vs ゲームサーバ

その後のDeNAのネイティブアプリ開発

そして、Webサーバーと、アプリにおけるゲームサーバーというのは役割が違うので、ここの設計思想の違いは、現状でも課題になっています。

その後のDeNAのネイティブアプリ開発

元々の戦略として、クライアントにゲームロジックや各種制御を寄せましょうということをしていました。
実は、Sakashoの方が先行して開発されたので、当時のゲームサーバーを担当していたメンバーは、「急に言われても、設計切り替えられないし、クライアント開発とかもあまり始まってないからどういう世界観を目指してるのかあまりわからないな」という感じだったんですね。
結構チーム内で言われていたのですが僕が「クライアントはこういう作り方をするんだよ」と話しても「僕の頭はまだWeb頭でした」という、Webサーバーサイドの考えからアプリのアーキテクチャを含めたアプリのアクセスを受けるゲームサーバーへの切り替えに、半年くらい時間が掛かる人が結構多かったかな、と。

ちなみに、クライアント開発へ移行したエンジニアは結構早く技術はキャッチアップしていました。
「なんでなんだろうな」と思うと、「そもそもゼロベースなのでフラットに学習できました」であるとか。クライアントに関してはプロジェクトが始まってしまっているし、締切もあるしで必死にやってる内に覚えてしまう、というような、比較的学習効果の高い環境が用意されたのかな、と思っています。
それで、サーバーサイドエンジニアの転向よりは早かったのかな、と思っています。

となると、今はもう複数のアプリタイトルも運用されてますし、学習材料とかも開発案件は多くて、Webサーバーを開発してきたエンジニアがゲームサーバーを開発する環境も整ってきたのでキャッチアップも短くなってきたかなと思っていたのですが、結構まだ苦労している人がいます。

その後のDeNAのネイティブアプリ開発

「なんでサーバーサイドエンジニアのキャッチアップには時間が掛かるんだろう?」と思ったのですが、こんな理由なのかなと思っています。
そもそも論で言って、設計の切り替えというのは学習コストが必要です、と。
そして今、大きな壁になっているのかなと思うのが、クライアント開発スキルがあるわけではないので、自分でクライアント環境構築して、ソースコード読んで、クライアントってなにやってるんだろうというのを調べようとやっても結構ハードル高くて、そっちから情報を引っ張り出すのが難しい、ということです。

そして既存のサーバー側のコードを読んでも、クライアント側と処理が分担されているので、サーバー側だけ読んでも「この機能ってなんのためにあるんだろう」というのが直感的にわからない、と。
しかも汎用的に色々使われているので、ユースケースが様々でそれがよりわかりにくくなっている、と。
これについては結構悩んでいて、多分プログラマーなら誰でも1度は言われたことがある「コード読めよ」と言われても「いやいや読んだんですけど全然わからないです」といった状態になりがちなんです。
そんな中でもアプリは動いているので、運用のタスクもあり、CSからのお問合わせに対応したりだとか、なかなか学習するのに難易度が高い状態になっているな、と思っています。

その後のDeNAのネイティブアプリ開発

今日は、こんなことがありました、あんなことありましたという話をしたのですが、今、僕が、「これってどうやったら解決できるかな?」と思っているのが、クライアント開発についてはとりあえずやらせてみれば結構できるだろうということがわかったのですが、今までWebサーバー作ってきた人が、クライアントのアクセスを受けるWebサーバーを作る時に、いかに早くキャッチアップできるかというのは課題として続いているなということです。
振り返ってみると、この課題がずっと残っているので、ネイティブシフトしてみたら、実はサーバーサイドが一番辛かったんじゃないかと思っている、というお話でした。

ご清聴ありがとうございました。

会場:拍手


TechCon トップへ戻る

RECRUIT - 募集職種一覧

「DeNAのイメージを破壊」してくれる、ゲームクリエイターを常に募集しています。

EVENT - イベント

Game Developer's Meeting
PAGE TOP

DeNA for GAME CREATORS