Linear ArchiveArchived issues viewer
← Back to list
INS-846

バトル中断後 ホーム画面に戻ると ホーム画面voiceアサーションエラー(内部)し、BGMが脈絡なく停止する問題

StatusDone
TeamInstansys
Assigneeasuki.uehata@instansys.co.jp
PriorityLow
Created2026/06/12 04:31
Completed2026/06/26 08:02
Archived2026/07/04 00:50
Bug

Description

1-2 で起きた。


1-2 バトル開始し、バトル中断 リザルトの後、ホームに戻って mayaya の音声が アサーション失敗したら、 BGMが 何の脈絡もなく、停止しました。

以下ログです。


ーーーーーーー

ーーー

[Error] アサーション失敗: No sound matching alias 'sounds/se/battle/normal_mayaya.m4a'.
	(anonymous関数) (index-BVxTR0NS.js:16:2024)
	exists (index-BVxTR0NS.js:3408:44293)
	find (index-BVxTR0NS.js:3408:44446)
	_resolveSEPlayOptions (index-BVxTR0NS.js:3620:22852)
	playSE (index-BVxTR0NS.js:3620:23143)
	(anonymous関数) (index-BVxTR0NS.js:4215:209462)
	(anonymous関数) (index-BVxTR0NS.js:3445:2675)
	emit (index-BVxTR0NS.js:27:66793)
	update (index-BVxTR0NS.js:27:69218)
	(anonymous関数) (index-BVxTR0NS.js:27:67571)
	n (index-BVxTR0NS.js:16:5857)
[Error] TypeError: null is not an object (evaluating 't.addressModeU') — index-BVxTR0NS.js:53950
	(anonymous関数) (index-BVxTR0NS.js:16:2024)
	c (index-BVxTR0NS.js:3620:226573)
	(anonymous関数) (user-script:2:878)
[Error] TypeError: null is not an object (evaluating 't.addressModeU')
	n (index-BVxTR0NS.js:16:6010)
[Error]  (2)
TypeError: undefined is not an object (evaluating 'this._texturePool[n].push') — index-BVxTR0NS.js:22387{componentStack: ""}Object
	(anonymous関数) (index-BVxTR0NS.js:16:2024)
	c (index-BVxTR0NS.js:3620:226573)
	Mm (index-BVxTR0NS.js:3420:33190)
	(anonymous関数) (index-BVxTR0NS.js:3420:33522)
	Jt (index-BVxTR0NS.js:3420:12327)
	fa (index-BVxTR0NS.js:3420:12420)
	gt (index-BVxTR0NS.js:3420:65617)
	tr (index-BVxTR0NS.js:3420:86227)
	Rr (index-BVxTR0NS.js:3420:85531)
	Nf (index-BVxTR0NS.js:3420:80961)
	fg (index-BVxTR0NS.js:3420:80626)
	Ge (index-BVxTR0NS.js:3420:8803)
	Be (index-BVxTR0NS.js:3420:7568)
	tr (index-BVxTR0NS.js:3420:86579)
	Rr (index-BVxTR0NS.js:3420:85531)
	Nf (index-BVxTR0NS.js:3420:80961)
	fg (index-BVxTR0NS.js:3420:80626)
	st (index-BVxTR0NS.js:3420:8682)
	$ (index-BVxTR0NS.js:3413:37004)
[Error] Failed to load resource: the server responded with a status of 413 (Request Entity Too Large) (envelope, line 0)

Comments (4)

asuki.uehata@instansys.co.jp2026/06/12 06:07

厳密に分析した結果、再現性がなかなか限定的であり、高速で画面遷移させれば生じる問題であるようだ。再現性は限定的であることから一旦、解析 修正は、後回しにする。

クロスフェード FadeIn FadeOut系のVolume制御の問題かもしれない。

asuki.uehata@instansys.co.jp2026/06/12 06:08

なお中断は、バトル中だけでなく、ステージ選択画面での中断でも同様の問題が生じた。

リザルト画面から高速でホームへ遷移しようとすると本件バグが生じやすいことまでわかった。

asuki.uehata@instansys.co.jp2026/06/26 08:02

アサーションエラーでは、ないが、バトル中断後 BGM停止する問題が起きる前と起きた時の比較で、instVol が、正常時 0.25 異常時1.0 ということがわかった。

結果、異常時に以下 診断スニペットを Safariで実行することで問題解析をおこなった。

({
  // 既存
  curAlias: __sm._currentPlayingAlias,
  hasInst: !!__sm._bgmInstance,
  instVol: __sm._bgmInstance?.volume,
  final: __sm._bgmFinalVolume(),

  // ★ dead pointer 判定の本命
  aliasIsPlaying: __pixiSound.find(__sm._currentPlayingAlias)?.isPlaying,
  aliasIsLoaded: __pixiSound.find(__sm._currentPlayingAlias)?.isLoaded,
  aliasInRegistry: __pixiSound.exists(__sm._currentPlayingAlias),
  perSoundVol: __pixiSound.volume(__sm._currentPlayingAlias),

  // instance 側の内部状態
  instProgress: __sm._bgmInstance?.progress,   // 0〜1 で進行中なら増える
  instPaused: __sm._bgmInstance?.paused,
  instLoop: __sm._bgmInstance?.loop,

  // 並走 instance 数(pixi-sound 内部)
  instCount: (() => {
    const s = __pixiSound.find(__sm._currentPlayingAlias);
    return s?.instances?.length;
  })(),
  instSame: (() => {
    const s = __pixiSound.find(__sm._currentPlayingAlias);
    return s?.instances?.includes(__sm._bgmInstance);
  })(),

  // transition token (二重 playBGM の証拠)
  token: __sm._bgmTransitionToken,
})

結果以下となり、問題コードが絞り込めた。


aliasInRegistry: true

aliasIsLoaded: true

aliasIsPlaying: false

curAlias: "https://utsaqkhxqllqkazxzhow.supabase.co/storage/v1/object/public/sounds/sounds/e105a489-0ab7-4dfa-bb93-db494318d6c2/6c10b55c-59fd-4b95-ad9f…"

final: 0.25

hasInst: true

instCount: 0

instLoop: false

instPaused: false

instProgress: 1

instSame: false

instVol: 1

perSoundVol: 1

token: 36

診断結果まとめ

hasInst: true           _bgmInstance は参照保持
instSame: false         ★ pixi-sound 内部の instances リストに居ない(detached)
instCount: 0            ★ alias 上に生きてる instance はゼロ
aliasIsPlaying: false   ★ 鳴っていない("聞こえない" の正体)
instProgress: 1         このインスタンスは「終端まで到達した」状態
instLoop: false         ★★ BGM なのに loop:false(playBGM 経路では必ず loop:true のはず)
aliasInRegistry: true
perSoundVol: 1          per-sound 層は正常

dead pointer 確定。INS-815 と同型の罠です。_bgmInstance は生きているように見えるが、pixi-sound 側ではそのインスタンスは既に detach されていて、別のどこかで stop された状態。 ーーー

最も怪しい原因

instLoop: false が決定打。BGM 経路は sound.ts:1294loop: true をハードコード。なのに loop: false のインスタンスが _bgmInstance に入っている。

これは playBGM の race ではなく、playOneShot(voice) または何か別の sound.play 経路で生成された instance が _bgmInstance に紛れ込んだ可能性が高い、と思いきや、_bgmInstance への代入は _ensureMainPlaying の line 1324 一箇所しかないので、それは無い。

より妥当な仮説:

  1. BGM playBGM が走る
  2. 同じ alias の sound.play を内部で再利用するため、pixi-sound が 既存のインスタンスを返してくる ケースがある(特に Luna BGM が singleInstance 相当の設定で add されていた場合や、直前に何らかの sound.play が同 alias で走っていた場合)
  3. その既存インスタンスはすでに「loop:false で再生終了済み」の orphan
  4. _bgmInstance = playInstance でこの orphan を保持してしまう
  5. その後の fadeIn timer は _bgmInstance.volume = ... を書き込むが、orphan なので音は出ない → 最終 volume 1.0 (= fadeIn 完了時に _bgmFinalVolume() を書いた値? いや 0.25 のはず…)

instVol: 1 の値の出どころが完全には説明できていないので、もう一段絞りたい。

ーーーー

Home BGM (Luna 選択時) で playBGM が二重発火 + singleInstance: true の組合せで dead pointer 化

決定的な証拠:

  • addSoundIfNeededsingleInstance: true で alias を登録する (preload.ts:103)
  • Home マウント時、playBGM(LunaURL) を 2系統が並走 で叩く:
    1. usePreloader.ts:86 — preload 完了直後の playBGM(initialBgm.alias, ...)
    2. Home.tsx:523isLoading/queryData 依存の useEffect (ポーリング後 playBGM)
  • instLoop: false が示すとおり、_bgmInstance は loop:true で開始されたはずの BGM instance ではなく、stop された後の orphan を握っている

Raceの流れ

Home BGM (Luna 選択時) で playBGM が二重発火 + singleInstance: true の組合せで dead pointer 化

決定的な証拠:

addSoundIfNeeded は singleInstance: true で alias を登録する (preload.ts:103)
Home マウント時、playBGM(LunaURL) を 2系統が並走 で叩く:
usePreloader.ts:86 — preload 完了直後の playBGM(initialBgm.alias, ...)
Home.tsx:523 — isLoading/queryData 依存の useEffect (ポーリング後 playBGM)
instLoop: false が示すとおり、_bgmInstance は loop:true で開始されたはずの BGM instance ではなく、stop された後の orphan を握っている

「voice 喋り出しが大きい時に出る」のは、voice の playOneShot がメインスレッド/iOS XPC を一瞬詰まらせて A と B のタイミングがズレ、上記 race が綺麗に成立する条件になるためと思われます(早い遷移で再現する事象とも整合)。

なぜ「正常時」と「不具合時」が分かれるか

  • 正常時: A と B の到着間隔が十分離れる、または順序がうまく揃って _currentPlayingAlias === alias && isPlaying の短絡 (sound.ts:1178-1184) で B が no-op になる
  • 不具合時: B が A の await 中(isPlaying がまだ false)に到着 → 短絡が外れて二重 sound.play → 上記 race

ーーーー

asuki.uehata@instansys.co.jp2026/06/26 08:02

一旦、メモリリークの問題と合わせて解決した。