はき違えたナラティブ、『SUPERHOT MIND CONTROL DELETE』雑感

store.steampowered.com

f:id:appalerm:20210329090129p:plain

手裏剣キャッチとか瞬間瞬間のゲームプレイは良いとこもあるんだけどなあ。最終的にはPS Vitaのガールズ&パンツァー以上に怒ることになった。

以降には本編の結末に関わるネタバレを含みます。


テーマとしては「ゲームの本筋を99%終えたとき、残りの1%を見たくなるのはなぜか?」という問題提起ではあるだろうが、その方法は粗雑に過ぎたのではないか。

ゲームの終盤、主人公は五感のすべてを捨てSUPERHOT世界の(クウ)に至る。ゲームの機能のすべては見かけ上破壊され、アプリケーションを起動しても「SUPER」と「HOT」を繰り返し唱えるだけ。プレイヤーとゲームが合一する瞬間である(そうだろうか? そういうことにしておこう)。

そこで終わっていれば美しい完結だったかもしれないが、空即是色。「これは完全な終着だ。お前のゲームは終わったのだ」としきりに叫ぶSUPERHOT世界の意志(?)を無視し、主人公は散らばった自我を再構築することができる*1

f:id:appalerm:20210329090308p:plain

具体的にはこの画面で2時間半拘束される。

スキップ不可のプログレスバーが伸びるだけの画面はゲームに許される演出のエッジを探っていると表現すれば聞こえはよいが、こんなものは『たけしの挑戦状』がとっくに通過した地点であり、たけし以外が何故ほとんどやってこなかったかと言えば、単につまんねえからだよ。

(初期案では24時間、初回リリース時には8時間だったのがアップデートで2時間半に短縮されたという話を知って呆れてしまった。たけしだって5分が正ルートだろ)


「時間の浪費」をあえて作り出すならば、製作者は何か意味を込めているに違いない。たとえばプレイヤー自身の探求欲を自覚させるとか……それは分かるし、開発者がどんなゲームを作ろうと自由ではあるけど、「押しつけがましい」という感想を述べるのもプレイヤーの自由だ。

Xbox Series Xを2時間半空転させた俺の前で、果たして世界はリストアされ、特に報酬のない追加ステージと、いわゆる「オワタ式」のサドンデス・モードがアンロックされた。SUPERHOT世界の集合意識は「この先に新しいPerkやステージは無い」と引き留めるときに言っていたのでウソがばれたが、2時間半待ったなりの感動・情動が待っているわけでもなかった。破壊されたゲーム機能を無意味な時間をかけて復帰した、というのが、ほとんど正確なところだ。

魔法は解けた。がらくたを片付けているような気分のところに、「ゲームをやめた皆さん、おめでとうございます! あなたの判断を私たちは尊重します。ゲームをやめずに戻ってきた皆さん、ありがとうございます! いずれの選択もあなた方の『ナラティブ』、かけがえのない体験です!」という声が聞こえた気がした。


ゲームを終えた(あるいは再開した)俺は、開発者に「SUPERHOT MIND CONTROL DELETEは、この無意味な時間をかけてでも遊ぶべきゲームだろうか?」という問いを突き付けられた、と感じた。

うんざりだ。ゲームは初めから何処でやめてもいいものであって、ゲーム内存在にダチョウ倶楽部のごとく「やめろ」と言われるものではないし、製作者に「ゲームはどこでやめればいいのでしょうか。おうちのかたと一緒に考えてみましょう」と言われるものでもない。あるいは言ってもいいがお前の言いかたは気に食わない。この場合「遊ぶべきかどうか」という問いかけそのものが野暮の極みじゃないのか。

放っておけば当分同じゲームをやり続けるだろう俺のようなアホ人間に、「これからプレイヤーに仕打ちをかますけど、それでもゲームを好きでいてくれる?」と、くだらない試し行動でゲームとプレイヤーの関係を計ろうとしたのは、このゲームを好きになって貰うためか? それとも嫌いになって貰うためか?

現代アート気取りのナラティヴこっごさえ無ければ、もっと好きでいられたかもしれないし、もっと遊んでいられたかもしれない。


坊主(オチ)が憎くなってきたのでついでに袈裟(なかみ)の話をしよう。そもそもシリーズ3作目である『MIND CONTROL DELETE』は前作までと比較してゲームデザイン自体がプレイ時間の水増しに特化していたようにしか見えないが、開発者はどこまで自覚的だっただろうか。

元来「自分が動けば相手も動く」のワンアイデアで3作も引っ張るのは難しかったように思う。Perkで能力に幅を持たせ、ローグライク方式でリプレイ性を確保し、ゲームとしての限界を先延ばしにする試みは、ある程度は成功している。

しかし全体として、特に難易度のコントロールをステージの連続クリア数に頼ったことは、単調なステージを何十何百と繰り返させるゲーム進行の無味乾燥さに直撃している。能力強化の爽快感はそんなリトライのストレスを埋め合わせるに足りていないし、それどころかアイテム運による自機性能のブレは、高難度チャプター(難しさの理由:ステージ数が多い)の初めからのリトライをますます強いてくる。

ツモ次第の運ゲーになりはてたゲームデザイン。抽象・断片化が前作以上に進み難解さを増したストーリー。「味のしないガム」という言葉はクリア前から頭をよぎっていた。

仮にエンディングが「無意味な時間をかけてでも遊ぶべきゲームだろうか?」という問いかけだったとして。YESと言わせるつもりなら自信が強すぎるし、NOと言わせるつもりなら皮肉が強すぎる。


"We try to leave our games free for interpretation to the players and wouldn't like to push our own narrative," Skorupka said. "It's much more powerful for someone to filter the game through the lenses of their own experiences. That said, in my view the original Superhot is more about addiction and Mind Control Delete is about greed and over-attachment."

The new Superhot forces you to wait hours after the ending before you can play again • Eurogamer.net

Eurogamerによれば開発者は、「(開発者の言に左右されずプレイヤー諸氏の体験を大事にして欲しいとしつつも)SUPERHOT1作目では中毒を、MIND CONTROL DELETEでは貪欲と過度の執着をテーマにしている」と述べている。「ゲームの本筋を99%終えたとき、残りの1%を見たくなるのはなぜか?」「無意味な時間をかけてでも遊ぶべきゲームだろうか?」という問いかけとして解釈するのは、そこまで外したものでもないはずだ。

このゲームのエンディングは、キャンディの箱をとりあえず底までさらいたがるゲーマーの心理を逆手に取った、芸術性を狙った演出だと説明できる。しかし同時に芸術性を建前にしてゲームの完成度をごまかそうとしてはいないだろうか。上記のEurogamerの記事では友達とゲームの話をして欲しいだのと「議論が深まっ太郎」のようなことを仰っているようだが、要するに日本語で炎上商法と言うやつじゃあないのか。

仮に、SUPERHOTの水増しという自覚があればこそ「お前が味のしないガムをそれでも一生懸命噛もうとしていたのは何故か? それは欲であり人間の本質だからだ! これがお前たちのナラティブ! ご清聴ありがとうございました!」と最後っ屁をかましに来たのであれば悪意まで感じるし、返品期間の回避や統計平均プレイ時間の延長のためにやっているなら芸術なんかじゃなく、ただのセコい悪事だ。

英語メディアではIGNなど幾つかのサイトで話題になったらしい(待ち時間をキャンセルするパッチの話だったりするが……)反面、日本のウェブメディアがこのゲームのエンディングに触れたことはないようだ。それは良し悪しあるのかもしれないが、個人的にはこんな底意地の悪い釣りのごとき所業が取り上げられなくて良かったと思う。何より、最後にもう一度書くが、たけしの挑戦状より30年以上遅いのだし。

*1:初代と2作目もゲームができなくなること以外は大体そのようなSUPERHOTに最接近するオチだった気はするので、同じことをしても仕方ないのは、それはそうだが。

技術的限界で「ズッ友」になれません――『ららマジ』にみる仕様の衝突

『シン・エヴァンゲリオン劇場版:||』良かったですね。これはネタバレではないと思いますが、当時TV版に対して「なんだか分からないけど面白い番組が、最終回だとすら気付かないままなんとなく終わっていた……」と思った子供としては、あんなに面倒なものを終わらせることができた、終わらせてくれただけでまずは最高だと感じていますし、話を畳めないままに最終回ということにしなくちゃならないタイトルは世の中にごちゃまんとあるのでした。

f:id:appalerm:20210316235857p:plain

ズッ友(正式表記「ずっとも」)にも、なれなかった……。


f:id:appalerm:20200603174552j:plain

f:id:appalerm:20200603174213j:plain

去る2020年6月3日、ついに『ららマジ』のサービスが終了しました。開発のWright Flyer Studio改めWFS社にはガチの確率操作だったアナザーエデン事件のツケを今からでももっと真面目に払うべきではないのかと思っていますが*1、それは置いても色々と惜しいタイトルでした。暫定最終回イベント「ホニャららDREAM」のストーリーは本当に面白かった。

ただ記事タイトルの通り、今日するのはイベントの話でも写真の村山下貯水池第一取水塔の話でもないです。

f:id:appalerm:20210317001800p:plain

本作は一部プレイヤーの間で「データ通信量が多すぎる」「タイムアウトエラーが多すぎる」という苦情を抱えていました。今回は1年3ヶ月ほど前の読みづらいエントリのリライトとして、ららマジに何が起きていたのかをそこそこ分かりやすく説明するつもりになり、また何が起こらなかったのかを指摘していきます。

いや、サ終タイトルの不備なんてそんな死んだ子の歳を数えるような、後知恵で人の仕事をつつきまわす真似はいかがなものかと私も思うのですが。

ららマジはこんなゲームでした

f:id:appalerm:20210316231503p:plain

改めて『ららマジ』は、東奏高校・器楽部の生徒たちを編成し、彼女たちに「ドレス」と呼ばれるカードを装備させて戦う横スクロールアクションゲームです(……でした)。

キャラクター自身は戦闘パラメータを持たず、ドレスの組み合わせが戦闘能力になる仕組みを採用しています。

f:id:appalerm:20210316232334p:plain

1チームには最大4名を編成し、ステージセレクトの際に他プレイヤーからヘルパーキャラを借りて5名でゲームを開始します。

また上の画面では左右スワイプでチーム編成を切り替えることができ、10チームまでの編成を保存できます。

f:id:appalerm:20210316231704j:plain
ららマジ MPについて考える | クマー(・ω・)より)

編成中キャラクター詳細画面。画面上部に大きく表示されているのが操作キャラとなる必須のメインドレス、中央から下部にかけて「通常ドレス」「イベントドレス」と書かれているのが能力を底上げするサブドレスとなります。

サービス運営当時、キズナLv(キャラクター親愛度)は13まで解放され、サブドレスのスロットが5個まで使えるようになっていました。

f:id:rarasymphony:20180201131424p:plain
ドレスノートって何? - 【ららマジ】アンサンブルを奏でたいより)

それぞれのドレスは経験値などの付帯情報を持つ他、ドレスノートと呼ばれる最大64個前後のスキルツリー・アンロック要素のリストを持っています*2。これは解放数が多いほど増える可変長のデータです。

  • チーム(x 10)
    • キャラクター(x 4)
      • キャラクターの付帯情報(キズナLvなど)
      • メインドレス(x 1)
        • ドレスの付帯情報(経験値など)
        • ドレスノート(x 64)
      • サブドレス(x 5)
        • ドレスの付帯情報(経験値など)
        • ドレスノート(x 64)

したがって「チームの編成」とは、ざっくり上記のような階層構造で表せます。

大きすぎる通信データサイズの内訳を検討する

階層構造を簡単な図に開いてみます。

f:id:appalerm:20210317003505p:plain

図の右下に、チーム1個分に必要なデータ量をラフな実測に基づき追記しているのですが、1カラムあたり数バイト~十数バイトで済んでいるはずの他のデータに対してドレスノートだけが異常に大きいため、実質的にはチーム編成のデータ量≒ドレスノートの数であると言えます。

実際に計算していきましょう。

単位 ドレスの数 ドレスノートの数 データサイズ
ドレスノート1個あたり - 1 100byte
ドレス1着あたり 1 64 6,400byte
キャラ1人あたり 6 384 38,400byte
1チームあたり 24 1,536 153,600byte
10チームあたり 240 15,360 1,536,000byte

ドレスノートはなぜか1個あたり約100バイトの情報量を持ちます。したがってドレス1着分なら6.4キロバイト、キャラ1人あたりドレス6着で38.4キロバイト、チームには4人居るから153.6キロバイト10個小隊を編成すれば1.53メガバイトです(同じIDのドレスを参照していてもドレスノートは重複します)。

ステージ準備画面(ヘルパー選択画面)の応答データでは、画面のオモテに現れないはずのこうしたドレスノートなどの仔細をなぜか内包していたと考えられます。このため画面遷移は極度に遅くなり、イベントなどの混雑時にはサーバーや通信経路の帯域を食い潰すようなタイムアウトがしばしば起こっていました*3

f:id:appalerm:20210317001845j:plain

裏を返せば、10チームすべてを実戦的な編成にはせず、キャラを減らし、ノートを解放していないドレスだけで「空きチーム」を組めばデータの増加を遅らせることもできてしまう。データの伸び縮みが激しすぎる印象です。

……というのが通信量監視ソフトなどから推測した起こっていた事の話で、前回の記事(同じことを書いているので読まなくていいです)のおさらいでした。

「ずっとも」になれない!

ここからは起こらなかった事を検討します。

f:id:appalerm:20210316231704j:plain
ららマジ MPについて考える | クマー(・ω・)より)

注目すべきはキズナLv(親愛度)に応じてサブドレスの装着スロットが開放されるという仕様と、画面上で10個まで用意だけはされていた空きスロットの存在と……。

f:id:appalerm:20210316235857p:plain

そして、キズナLvは「仲間(Lv13)」が到達上限であり、「いないと寂しい(Lv16)」「ずっとも(Lv19)」「親友(Lv22)」「大切な人(Lv25)」「???(Lv28)」の解放予定は未定のままだったという事実です。

なぜキズナLvとサブドレススロットはリリースされなかったのか? ゲームバランス調整など運用上の工数も当然考えられますが、しかし理由として大きいのはやはりデータ量とタイムアウトではないでしょうか。

この記事の前半では、「チームにセットされているドレスの、解放済みドレスノートが多いほどデータ量が膨らむ」という構造を示しました。ならばキャラクターあたりの装着可能ドレスが増えていくと、データも合わせて肥大化するのが道理です。

1人あたり装着数 x 編成 x チーム数 ドレスの数 ドレスノートの数 データサイズ
ドレス6着 x 4人 x 10チーム 240 15,360 1,536,000byte
ドレス7着 x 4人 x 10チーム 280 17,920 1,792,000byte
ドレス8着 x 4人 x 10チーム 320 20,480 2,048,000byte
ドレス9着 x 4人 x 10チーム 360 23,040 2,304,000byte
ドレス10着 x 4人 x 10チーム 400 25,600 2,560,000byte
ドレス11着 x 4人 x 10チーム 440 28,160 2,816,000byte

全チームが実戦的な編成であれば、データ量の推定値は実に2.8メガバイトにのぼります。たかが出撃準備画面ひとつに3メガ近いダウンロードが発生するのは強烈なゲーム体験と呼ぶほかなく、外出先で軽く周回するだけで月のデータ利用枠を食い潰す……なんて話が冗談になりません。

結論はこうです。

エンドコンテンツの深化に向けて、キズナLv(≒装備スロット)の拡張は動作としては可能であり予定もされていたが、「通信量が膨らむ」というユーザー体験・サーバー帯域等の限界に突き当たり、無期限の延期に至ったのではないか。

多くの運営型ゲームの目指すところの「ゆるやかなインフレ傾向」の行く先のひとつが、実はあらかじめへし折られていたとしたら。このデータ量問題は表面上のユーザー体験以上に、開発運営にとってのゲームデザインに影を落とし続けたのではないでしょうか*4

余談ですが、これに近いことはドレス一覧画面やドレス着脱操作など多くの画面で「所持中の全ドレス・ドレスノートのデータが毎回ダウンロードされる」挙動として確認されており*5、要するに、全体的に、長くしっかり遊んでいるプレイヤーほど一直線に体験の悪化するゲームでした。長く運営することを目標とするタイトルにあってヘビーユーザーに新カードを取ってもらうのをメインの収入源としていた以上、そうすればするほど強い不利益を受けるなどという悲惨さが修正されなかったのだから、ある意味では「先のないシステムが終わるべくして終わった」という言いかたはできます。

以上です

ここまで言うからには自分だったらどうするか。通信量だけで言えば返却データをコンパクトに整形するのが正道として*6、邪道としては編成可能チームを3くらいまで減らすとかでしょうか。いずれにせよ怠慢だとか技術力が低いとか言いたいのではなく、起こったことには致し方ない理由や事情があり、そしてたかがデータダウンロードに見えても色々な工夫や落とし穴があるねというスクメロの回と全く同じ結論になってしまいますね……。

と同社後続タイトルでは直っているであろう胡乱なことをブツブツと書いてきましたが、サービス終了後もららマジは変わらず応援しております。ノベライズ版は書籍・電子のセットに出資しました。グッズやクラウドファンディング、噂の聞こえてくる中国版など、ゲームが終わっても今後のプロジェクト展開に一層の実りがありますよう祈っております。

*1:「引き直し」という意図がはっきりしていた以上、ドッカンテーブルのごとき表示上のバグなど吹き飛ぶレベルで悪質じゃないのか、と個人的には思っています。

*2:実際のデータ構造として内包されているか(Object-in-Objectのようになっているか)は本題ではないし、確認していません。

*3:いわゆるソーシャルゲームの、ステージ1周あたりに必ず呼ぶAPIで1メガバイトを超える通信を行う例はかなり珍しいと感じます。また多くのタイトルでは、大量のデータをAPIに載せると予期される場合は通信内容を圧縮するのが一般的です。本作でもgzip圧縮の跡はありますが、圧縮前から暗号化により見かけ上の情報量が限界近くまで激増しているため意味をなしていません。

*4:キズナLvの上限だけ先に解放して(ストーリーだけ進展させて)おいて、スロットの拡張を後回しにすれば「ズッ友」にはなれたと思いますが、それは根本的な解決ではない……。

*5:他にも「ステージ一覧は裏で期間限定ベントを含む全ステージのクリア情報をダウンロードしているらしい動きをする」など、チューニングの微妙な箇所は多かったようです。

*6:ローカルキャッシュを活用するというのが第一として、後はおそらくノートのレコードをそのまま返しているところを、画面によっては返さないようにするとか、必要だとしてもノートで増幅されるパラメータの合算値で返すとか、解放済みノートIDの配列で返すとか、方法そのものは幾つか思いつきます。暗号化のせいでgzip圧縮が全くと言っていいほど効いてないのを改善するのも有りだと思う。

なぜスクメロのアセットダウンロードは遅かったか(あるいは、なぜスクストは速いのか)

この記事はスクールガールストライカーズ2 Advent Calenderの9日目です。

f:id:appalerm:20201209093210p:plain

スクールガールストライカーズ トゥインクルメロディーズ(公式サイトが消滅したのでどこにもリンクをはれない)、以下スクメロがオフラインアプリケーションに移行して早いもので2年が過ぎました。このタイトルには思うところがあって、終了を期に書いた感想記事でも結構な長さで「とにかくアセット(リソース)ダウンロードが遅かったんだよなあ」と書いています。

これ以降ちょっと興味が沸き、スクメロのサービスが終わった後も他タイトルを含めてファイルダウンロードへの向き合い方についてたまに調べるなどしていました。今回はそんな幾つかの事例についてお話しできればと思います。

目次

「往復の待ち時間」の話

前提として、いわゆるゲームアプリでのファイルダウンロードでは、今のところはまだ多くの環境でHTTP(HTTPS)/1.1というワールドワイドウェブで長らく使われてきた方式を採用しています。

純化のためHTTPSでなくHTTPで話を進めるとして……。

f:id:appalerm:20201209092245p:plain

  1. 「これから通信を始めたいです」とサーバーへ伺いを立て、了解を得る
  2. 欲しいファイルのパスをサーバーに伝えると、ファイルが返ってくる
  3. 「通信を閉じます」とサーバーに通知し、その到達確認を得る

1番と3番にあたる前準備と後処理(SYN, ACK, FINという小さなTCPパケットの要求応答)を含めれば、3回の往復をもってファイルのダウンロードは完了します*1

接続を切らずに使いまわすKeep-Alive仕様によって1番3番の回数は大幅に省略できますが、とはいえ1個のファイルダウンロードのためには要求・応答のペアが1回以上存在するという原則はHTTP/1.1を使う限り変わりません。

通信が往復するということは、その分だけ待ち時間があることを意味します。「このファイルを寄越せ」という要求がサーバーに届くまでと、それへの応答がサーバーからクライアントへ届き始めるまでに、距離や設備などの理由で時間がかかるわけです(遅延、レイテンシと呼ばれます)。

Wi-Fiと仮定 モバイル通信と仮定
RTT(=信号が往復するために必要な時間) 10ミリ秒 100ミリ秒
遅延時間の合計(ファイル100個のダウンロード時) 1秒 10秒
遅延時間の合計(ファイル1000個のダウンロード時) 10秒 100秒
遅延時間の合計(ファイル10000個のダウンロード時) 100秒 1000秒

仮にファイル1個のダウンロードに対し通信の往復が1回あったとして、当たり前ですが10倍の遅延があればムダな時間は10倍に膨れ上がりますし、ファイル数が10倍あればやはりムダな時間が10倍になります。

つまりダウンロードにかかる時間とは、帯域や遅延など回線の都合と並んで、往復回数と実際に待った時間がキーであると言えます。とりわけ「たくさんのファイルを」「ひとつずつ順番に」ダウンロードする場合には、遅延が大きくなって立ちはだかってくるのです。

ダウンロードの工夫

世のアプリゲームでは数千数万のアセットを扱うことも珍しくありません。これらがどんな対策で快適さをねらっているのか? というのを、知っている範囲で幾つか紹介します。

並列処理

ゲームだけでなく多くのアプリケーションで行われているであろう方法として、複数のファイルを同時にダウンロードするというものがあります。

f:id:appalerm:20201209012426p:plain

たとえばこれはWebブラウザでF12を押すと出るやつ(デベロッパーツール)の画面ですが、ページを読み込ませてみるとタイムライン上でファイルのダウンロードが重なっていることが分かります。

ダウンロード処理が別々に動き、待ち時間の間に別の通信を滑り込ませることで、通信経路のヒマな時間を減らしていけるわけです。経路が物理的に分かれるわけではないので限界はありますし、並列数を増やしすぎるとかえって逆効果になることもありますが、例えば細かいファイルが多い場合に4~6程度の並列数があれば、遅延時間をじゅうぶんに削れることが期待できるかと思います(現代のWebブラウザの並列数は6が多いようです)。

ファイルの結合(既存のアーカイブ形式)

「そもそもファイル1個あたりに通信の往復が起こるのをやめたい」という考えから、あらかじめファイルを結合しておくことで往復の回数を減らすトリックがあります。10000個のファイルでも直列に繋げてしまえば大きな単一のファイルとして素早く落とせるという発想です。

たとえばUnityではAssetBundleというアーカイブ形式がサポートされており、ゲームで使うファイルをシーンやキャラクターなど適当な単位でひとまとめにしておくことで、総ファイル数を抑えたり、開発の見通しを良くすることが可能です。

この「細かいファイルをたくさん送りつけるよりも一つのファイルにまとめてしまう」という考えは合理的で、ゲーム以外にも多くのところで使われています。PC用アプリケーションのインストーラが実行ファイルや圧縮ファイルひとつで配られているのもファイルの結合という振る舞いですし、言ってみれば我われがファイルを送る時にzipなどにまとめるのも、ファイルひとつひとつに意識を割くことを避けるという意味では高速化の一手段です。

ただ程度によって善し悪しはあり、ゲームアセットの場合は部分的な更新でもファイル全体をダウンロードせねばならないペナルティも起こるので、分割単位は管理の楽さや実効性能、更新頻度などの綱引きでバランスを取ることになるはずです。一桁MBくらいで「ちぎり」始めるのが現実的でしょうか。

ファイルの結合(禍つヴァールハイトの事例)

同じファイル結合ですが、独自の形式でダウンロードの処理を工夫している例もあります。

www.slideshare.net

Klab社では「禍つヴァールハイト」で採用された方法のスライドを公開してくださっています。

f:id:appalerm:20201209012952j:plain
【Unite Tokyo 2019】「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック p.94

並列数の調整に加えて更にHTTP/1.1 Range Requestsを採用しており、これはファイルの範囲……「何バイト目から何バイトの間」をサーバーに要求し、その範囲の部分だけをダウンロードするという仕様です。

f:id:appalerm:20201209013033j:plain
【Unite Tokyo 2019】「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック p.96

これを使い、結合済みの大きな一個の無圧縮tarアーカイブから必要な範囲を確定し、少ない往復回数で多くのファイルをダウンロードできるという。

更に、ダウンロード速度とは直接関係ありませんが、ヴァールハイトではダウンロードしてきたファイルを個別にちぎってストレージに格納し、アプリからはそれぞれ細分化されたファイルとして扱えるようですね。

さらに、ファイルの結合(スクストの事例)

www.jp.square-enix.com

リリース順が前後しますが、このRangeリクエストはスクメロのスピンオフ元の「スクスト」でも非常に近い方法を採用していることが分かっています(独自調べ)。

f:id:appalerm:20201209013546p:plain
スクールガールストライカーズの内製クライアントエンジン p.76

スクストの場合は結合済みファイルをちぎらずにストレージに格納し*2、IDで抽象化しているという違いがあるようです。上記は運営初期のスライドですが、ファイルをバラバラに格納しないかわりに、スクリプトコンパイル時かアセット呼び出しの際にファイル名をアーカイブ名-ファイルIDのペアに変換する仕組みのように思われます*3

HTTP/2などのプロトコルに乗り換える(リーグ・オブ・ワンダーランドの事例)

一方でセガゲームス社(当時)の「リーグ・オブ・ワンダーランド」では、比較的新しい通信方式であるHTTP/2の導入を図ったという発表が行われていました。

learning.unity3d.jp

HTTP/2は現在広く使われているHTTP/1.1の欠点、たとえば先述した通信の往復回数と待ち時間の問題をまさに解決できるプロトコルです。

f:id:appalerm:20201209014457j:plain
大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~ – Unity Learning Materials p.28

上記のスライドではライブラリの少なさやサーバーの対応など課題はあるとしつつも、往復の影響が極めて小さく、帯域をフルに使えるという強力さが説明されています。

ファイルをまとめてダウンロードできるという観点でいえば、先の禍つヴァールハイトやスクストのようにファイルを結合するアプローチに近いものの、独自形式の煩雑さから逃れられるのは魅力的ですね。

スクメロはどうだったのか、仮説を考える

本題に戻ってきました。

遅延要因

ここまで見てきたアセットダウンロードとの戦いによって、スクメロが何をしたか、あるいは何をできなかったかを察せるような気がしませんか。先のKlab社のスライドに照らして、私の推測を書き出します。

f:id:appalerm:20201209015715j:plain
【Unite Tokyo 2019】「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック p.87

スクメロもファイルの分割数が多く、また、結合などのトリックが積極的に使われた形跡はありません。これはAndroid版のファイルシステムを覗けばrootを取らなくても分かり、全体では2万ファイル以上あったことが確認できています(サーバー上での結合もないことはパケットキャプチャから確認済みです)。

f:id:appalerm:20201209024357j:plain
【Unite Tokyo 2019】「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック p.92

ここからはどうしても推測になりますが、ダウンロードの並列化をしていないくらいのことでもないと説明のつかない遅さです。できればこれもパケットキャプチャのログを検討したいのですが、ログ取った端末の電源が入らなくなってしまった……。

f:id:appalerm:20201209015916j:plain
【Unite Tokyo 2019】「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック p.90

ダウンロードの間隔がメインスレッド、つまり画面の描画待ちに依存する……というのも、まさかあるのでしょうか。スクメロの使っているBestHTTPライブラリはメインスレッド非依存らしいのですが、メインスレッドを待つようにも書けるのならば可能性はある。

でなければ残りは、どこかにダウンロード処理の工夫を台無しにしてしまうようなボトルネックが挟まっていたというものしか考えられません。例えばデータの後処理……ファイルそのものの保存処理や、「ファイルを持っている」ことを管理情報(SQLite等)に書き込む処理など……が「メインスレッド待ち」に相当する制約を持っていて、ダウンロードと同期してしまっているような作りであれば、似たような待ち時間は発生し得ます。

結論

以上、素直に作るとハマってしまいそうなところとして、KLabのスライドで挙がっていたこの3つの確度が高いと今は考えています。

  • ファイルが多く、通信の往復回数が多い(確認済)
  • ダウンロードの並列化が行われていない(仮説)
  • ダウンロードかそれに付随する処理が、メインスレッドにブロックされている(仮説)

返す返すも、本当に余程のことがなければここまでの遅さにはならないと思うし、実際のところ何があったんでしょうね……。

まとめ

おさらいです。

  • 通信にはレイテンシ(到達時間)があり、通信回数(≒ファイル数)を増やせば増やすほどレイテンシの影響は大きくなる
  • 通信の並列化やファイル結合、通信方式自体の乗り換え(HTTP/2)などの方法でレイテンシの影響を抑えられる
  • スクメロは大量のファイルを結合をせずにダウンロードしていたし、並列化もしていなかった可能性がある

なので「スクストはなぜ速いのか」のほうの答えは、一因として「ファイルを積極的にパックして通信の回数を減らしている」ということになります。

「勝ちに不思議の勝ちあり。負けに不思議の負けなし」という格言に従えば、私はスクメロの早期のサービス終了の理由としてアセットダウンロードの遅さは十分に挙げられるレベルだったと思いますが、とはいえどんなタイトルも勝てば官軍、売れれば正義です。欠点を抱えた上でも初動で爆発的なヒットさえしていれば改修されていたかもしれない……とも、思います。

開発者にしてみれば上がらんかったパフォーマンスなど百も承知で、それでもリリースせざるを得なかったのでしょうし、怠慢だとか技術力が低いとかいうつもりはありません。起こったことには致し方ない理由があるのでしょう。今回はあくまでたかがデータダウンロードに見えても色々な工夫や落とし穴があるね(ここに書いた以外にもいっぱいあると思います)という主旨でした。

正確なボトルネックや、直面したであろう「致し方ない理由」については引き続きリバースエンジニアリング名人の名推理や関係者のタレコミをお待ちしています。秘密厳守。

*1:実際にはデータ受信中にもウィンドウサイズ毎にACKが飛び、もっと頻繁な到達確認が行われています。

*2:当初は単一のファイルだったようだが、現在は数十MB単位のアーカイブが複数並んでいると思われる

*3:深堀りしていないですが、ヘッダとインデックス、ダウンロード済み範囲の関係の整理はかなり複雑になりそうな印象です。差分ダウンロード実装当初、一部環境でリソースデータ破損に至っていたのはその辺が原因じゃないかと思う。