blog

審査の要らない場所に、先に出した

  • Claude Code
  • ゲーム開発
  • パフォーマンス

自分の Unity ゲーム SCRAP ARMS は、審査に3回落ちていて、いまは異議申し立ての最中だ。ストアでの配信日はまだ決まっていない。

別の出し先を探していて、YouTube Playables に行き着いた。YouTube アプリの中でそのまま遊べるゲーム枠で、収益化の手段は YouTube が提供する広告に限られている。調べて分かったのは、審査を回避できる話ではないということだった。Playables にも認証審査があり、しかも入り口自体が招待制だ。Developer Portal はまだ「Private Preview」のままで、応募は Interest Form 1枚。返答が来ない前提の文面で受け付けている。

それでも先に進めたのは、もう一つ分かったことがあったからだ。自分の Unity WebGL ビルドは、Playables の MUST を同時に3つ落としている。課金(IAP は一切不可、収益化は YouTube 提供の広告のみ)、通信(外部 URL の呼び出し禁止。自分の設計はサーバー権威なので、ローカル完結に作り直す必要がある)、そしてサイズ(初期バンドルが 30 MiB 未満)。この3つ全部を満たそうとすると、それはもう移植ではなく別製品を作る作業量になる。

正直に言うと、サイズについてはまだ確かめきれていないことがある。手元の調査記録には WebGL.data 106 MB、WebGL.wasm 84 MB という非圧縮値しか残っていない。元のファイルはもう無いので、圧縮をかけ直したらどこまで縮むかは測っていない。調査の時点でも「Addressables や Managed Stripping でどこまで落ちるか」を最初に確認すべき項目として挙げていて、サイズ単独で詰んでいたとは書いていなかった。詰んでいた理由は、3つの MUST を同時に満たすと別製品になる方だ。

だから判断はこうなった。広告のみ・ローカル完結の Web 版を Phaser で作り、審査の要らない自分のサイト ckludge.com に先に出す。YouTube Playables への応募は、その後でいい。

ゲートは、何も作っていない段階では入れていなかった

Phaser 版(games/scrap-arms-neo)を作り始めた日の commit を並べ直してみた。

15:05  パッケージ雛形
15:23  core の型・RNG・バランス定数
15:36  core のラン
18:15  レビュー修正
18:19  倉庫・ロードアウト・セーブ
18:22  セーブの読み込みの修正
18:26  元ゲームのスプライト取込
18:30  YouTube Adapter
18:42  Phaser シーン
18:57  レビュー修正
19:17  サイズゲート

サイズを機械的に測るスクリプトを入れたのは19時17分だった。コア・セーブ・スプライト・シーンが全部できたあとで、20時09分の最初の公開の前だ(間にサイトへ載せる commit と、後で書く CSS の切り出しが入る)。検査の中身は games/scrap-arms-neo/scripts/check-dist-size.mjs にこう書いてある。

//   MUST: 総量 < 30 MiB(初期バンドル=全部を初期扱い)、各ファイル < 30 MiB、ファイル名 [A-Za-z0-9_.-]、ファイル数 ≤ 8000

このスクリプトを入れた commit のメッセージには、当時の手順も残っていた。

check-dist-size.mjs は Playables Stability の MUST(総量/各ファイル<30MiB・
ファイル名・ファイル数)を検査し違反で exit 1。31MiB ダミーで赤(MUST 2件・
exit=1)を確認してから削除し、緑(13 files, 1.63 MiB・exit=0)を確認した。

わざと超えさせたダミーファイルで一度赤を見て、消して緑を確認する。壊れた状態で落ちることを確かめてから直す、というのは他の検査でも自分がよくやる手順だ。ただ、これを「まだ何も作っていない段階」でやったわけではない。中身がほぼ揃ったところで、枠のほうを検査可能にした。

13ファイルと14ファイル

公開当日の記録には、もう一つ数字が残っている。dist-youtube.zip(1.63 MiB / 14 ファイル)。サイズゲート導入時の「13 files, 1.63 MiB」と1件違う。

実際に zip を開いて確かめた。ディレクトリエントリ1件+実ファイル14件、非圧縮合計 1,713,784 バイト(1.634 MiB)。14で合っている。

理由は測り方の違いではなかった。ゲート導入から28分後の commit(89ed030)で、index.html に直書きしていた CSS を外部ファイルに切り出している。CSP のハッシュ許可を、ゲーム側の CSS が変わるたびに手で更新しなくて済むようにするための変更で、Vite がその CSS を1ファイルとして書き出すようになった。ファイル数が増えたのはこの1件分で、サイズがほぼ変わっていない(1.63 MiB のまま)のは、中身を移しただけで増やしていないからだ。

v0.11 まで、1.63 から 5.15 へ

そこから v0.11 まで、dist-youtube を測った値が harness/STATE.md と一部の commit に残っている。全部の版で測ったわけではないので、残っている観測点だけを並べる。

時点dist-youtube
サイズゲート導入直後(2026-09-15)13 files, 1.63 MiB
v0.2 公開直後(UI/VFX刷新)2.35 MiB
v0.2 の仕上げ(画像2枚を減色)23 files, 2.15 MiB
v0.3(遊べる化)2.80 MiB
v0.4(原作準拠の武器運用)2.79 MiB
v0.5(ブラスト・フルバースト)3.03 MiB
v0.8(武器アイコンをドット絵に作り直し)2.88 MiB
v0.9(ステージ4種・ボス/中ボス8体・ガチャ)4.76 MiB
v0.10(キャラクター3人)72 files, 4.88 MiB
v0.11(キャラクター2人を追加。この記事を書いた日)78 files, 5.15 MiB

v0.5 から v0.8 で一度減っている。武器アイコン20種をドット絵に作り直した commit を見ると、weapons.png が 221,914 バイトから 27,103 バイトに落ちていた。ここだけ見ると分かりやすい話に見えるが、同じ commit は fx_glow.png も削除していて、コード側も手持ち武器の演出(held.ts)やレベルアップ画面(levelup.ts)の新設、戦闘シーンの大幅な書き換えを含む大きな変更だった。しかも v0.5 と v0.8 の間には v0.6・v0.7・v0.7.1 が挟まっている。武器アイコンの軽量化は確かに効いているが、総量が減った理由をこの1件だけに絞れるほど単純ではない。

サイズを気にした形跡が全く無かったわけでもない。v0.2 の仕上げでは、演出用の画像2枚(fx_cutin.png・fx_death.png)を減色している。commit の前後のファイルで測ると、2枚で 209,006 バイト(約 204 KiB)軽くなり、dist-youtube は 2.35 MiB から 2.15 MiB になった。その commit のメッセージには「1065→807 KiB」と書いてあったが、commit の前後に残っている public/assets を合計すると 1,035,667 バイトから 826,661 バイトで、1065 は再現できなかった。ここでは測り直した方を書いた。

いま測ると、上限の6分の1

今日、同じスクリプトでもう一度測った。

$ node ./scripts/check-dist-size.mjs dist-youtube
dist-youtube: 78 files, 5.15 MiB
  SHOULD: file ≥ 512 KiB: assets/phaser-CYX5YQB3.js (1343 KiB)

MUST の上限(30 MiB)には遠く、SHOULD の総量上限(15 MiB)にも届いていない。引っかかっているのは Phaser 本体のバンドル1件だけで、これはゲームの絵ではなくフレームワークの重さだ。

内訳も見た。ボスのスプライト(boss_*.png)は16ファイルで1.22 MiB。v0.10 で足した3キャラクター分の絵とカード(hero_soldier_* / hero_ranger_* / hero_destroyer_* とカード画像)は9ファイルで0.33 MiB。合わせて1,631,623バイト、今の総量(5,402,438バイト)の30.2%を占める。ここに紛れ込ませそうになった罠があった。ボス系のファイルには MVP の頃からいる boss.png(25,023バイト)も別にあって、これは v0.9 で足した中ボス・ボスの絵ではない。ファイル名のパターンだけで数えると、居ないはずの1件が混ざる。

枠の中でどれだけ足すか、だけを考えていた

v0.10 までの commit を辿って感じたのは、絵を足すたびにサイズを細かく詰めていたわけではないということだ。v0.9 でボスを8体、v0.10 でキャラクターを3人足した機能の commit には、サイズの話が出てこない。測った値が残っているのは、ゲートを入れた commit、v0.2 の仕上げ、v0.10 の公開といった一部の commit と、harness/STATE.md の記録だけだ。

それで困らなかったのは、ゲートを入れたタイミングのおかげだと思う。中身がほぼ見えていた1日目の終盤、まだ何も出していない段階で、上限に近づいたら落ちる仕掛けを作った。以降は、その枠の内側でどれだけ足すかを考えていればよかった。記録に残っている版の値はどれも上限の近くにすら来ていない。1.63 MiB から始まって、今は5.15 MiB。上限の約6分の1のところにいる。

作業の分担も書いておく。実装の大半は codex に投げているが、全部ではない。クリック移動の目印(move-marker.ts)は codex が利用上限で2段とも落ち、Claude Code が自分で書いた。自分も実機で遊んで所見を返していて、v0.7 では16件、v0.8 では13件出している。仕様と検査の緑だけを見ていたわけではない。

YouTube Playables の Interest Form は、まだ出していない。今回作った Web 版は、その前にゲーム自体として ckludge.com に先に出してある。

STAGE10/50SCORE0BEST0COMBO×1貯蓄0KILLS0
TAP = FOCUS FIRE
強化ツリー倒した数で買う。1つの強化は1回だけ。枝は左から順に開く。
kill -9 agentKILLS 0
kill -9 agent 停止中