実機プレイ中 BGMぶつ切れ 効果音無音化 iPhone本体発熱 メモリリーク調査
Description
実機の検証で、キャラクター 強化画面で、強化素材を ぽちぽち増やしたり 減らしたり、強化してみたり、っていう操作をずっとやってたら、BGMが ブツって消えて、そのうち、操作で 選択する効果音が 急にならなくなったりして、やがてフリーズして、進行不能になり、iphone 端末が 発熱しだして、テストフライヤーで用意した このultemistのテストアプリが起動しなくなり、アプリ再起動もできなくなり、iOS 再起動せざるを得なくなった。
キャラクター 強化画面で ボタンをぽちぽちしている間に ボタンを押している回数分、メモリリークが起きていないか 確認するところから。
apps/client/src/lib/sound.ts:131 あたり?
Comments (3)
apps/client/src/lib/sound.ts:131 — system: true で SE を鳴らすパスが、毎回 new Audio(audioPath) を生成していて、プールもキャッシュもなく、明示的な解放もないか?
まず 再現と計測するところから
【報告】iOS 実機でのフリーズ・発熱事象の調査結果
現象
TestFlight ビルドにおいて、キャラクター強化画面で強化素材の +/- ボタンを繰り返し操作していたところ、以下の順序で問題が発生しました。
- BGM が途切れる
- 選択音などの SE が鳴らなくなる
- 画面フリーズ・操作不能
- iPhone 本体が発熱
- ultemist アプリが完全に起動不能になり、iOS 再起動が必要
原因(特定済み)
タップ 1 回ごとに new Audio() で HTMLAudioElement を生成している実装が原因と考えています。
- 該当箇所: apps/client/src/lib/sound.ts:131 の
system: true分岐 - 呼び出し元:
PushButton等、ゲーム全体のボタン類 - ブラウザが毎回オーディオファイルに対して Range リクエストを発行し、iOS の WKWebView 側ではネイティブのオーディオデコーダを都度初期化する挙動になる
- これにより WKWebView 内のオーディオチャンネル・デコーダリソースが連打で枯渇し、最終的にレンダラプロセスが OOM で落ちる
症状の順序(BGM 切断 → SE 停止 → フリーズ → OOM)が iOS WKWebView のオーディオリソース枯渇の典型パターンと一致しています。
調査で確認したこと
| 検証項目 | 結果 |
|---|---|
| Chrome DevTools Network | タップ毎に click.m4a の Range リクエストが発生することを確認 |
| Chrome ヒープスナップショット(dev) | HTMLAudioElement 数は増加せず(JS 側リークは無し) |
| Chrome ヒープスナップショット(prod build) | 同上(dev/prod 共に JS リークは無し) |
→ JS メモリリークではなく、iOS ネイティブ側のオーディオデコーダ処理コスト蓄積が主因。
修正案
対象ファイル: apps/client/src/lib/sound.ts(主)、apps/client/src/components/OptionModal.tsx(付随)
方針: new Audio() による毎回生成をやめ、起動時に @pixi/sound でプリロードした音源を使い回す実装に統一する。
修正規模: 小(数十行程度の差分)。ゲームロジックや UI には影響しない。
副次効果:
- SE 再生のたびにネットワーク層を通る無駄が無くなる(レスポンス性向上)
- CLAUDE.md 規約「
new Audio()を直接使わず SoundManager 経由」に完全準拠できる(現状 OptionModal に規約違反が残存)
優先度・リスク
- 優先度: 高。TestFlight テスト中にアプリ再インストール不能まで至っており、ユーザー環境でも同事象が発生し得る
- 修正リスク: 低。影響範囲は SE 再生経路のみ、ゲームロジック非依存
- 未検証事項: 修正後の iOS 実機での効果検証(TestFlight 配信権限の関係で自分では実施不可?)
ご相談事項
- 本件修正を優先タスクとして着手してよいか
- 修正後の TestFlight 配信・実機検証の進め方(誰がビルド・配信するか)
- 関連して
new Audio()直接利用を禁止する Lint ルール追加の是非