Contents — 7 sections

ダンスが終わったら、頭と手のTrackingを元に戻す。

やることだけ書けば簡単に見える。

MagiDanceでこの復帰経路を検査したところ、最初の結果は悪くなかった。

4ケース × 5回。

「Trackingへ戻し忘れている経路」は見つからなかった。

でも、見た目がおかしかった。

標準Emoteを再生すると、腕の向きにダンス最後の姿勢が混ざる。

最大で29°ずれていた。

Trackingは戻っていた。姿勢は戻っていなかった。

最初に見ていたのはTrackingの復帰だけだった

検査したかったのは、ダンス終了後に頭・手が通常Trackingへ戻るか。

終了理由はいくつかある。

  • 通常終了
  • 座る
  • AFK
  • 標準Emote
  • STOP
  • 再接触
  • 再読込

まずEditor上、Av3Emulatorを使って経路を検査した。

修正前の基準では、主要4ケース × 5回は通った。

つまり、

「Animationのまま戻らない」

という単純な不具合はなかった。

そこで終われば、PASSにできた。

でも別のLayerとの競合まで見ると問題が出た。

座る・AFK・標準Emoteを、自分のRestoreが上書きしていた

見つかった競合は4系統。

F1〜F3では、

  • Sitting
  • AFK
  • 標準Emote

が自分の都合でTracking / Animationを切り替えた直後に、MagiDance側のRestore処理がTrackingを書き戻していた。

MagiDanceから見ると「ダンスを終わらせて通常状態へ戻した」つもり。

でもVRChat標準側から見ると、

いまからSittingやEmote用のAnimationへ切り替えたのに、後からTrackingで上書きされた

ことになる。

「終了時はTrackingへ戻す」というルールを強くしすぎた結果だった。

さらに、Weightが残って最後の姿勢が混ざった

もう一つがF4。

ダンス終了後に標準Emoteを再生すると、腕の向きが最大29°ずれた。

原因は、DancelaveのAction Layerがダンス終了後も姿勢へ影響できるWeightを持っていたこと。

Write Defaults OFFの構成では、Layerが最後に書いた値を意図せず保持し続ける状況を作れる。

そこで DLV_ActionDance の既定Weightを0に変更。

ダンス中だけ VRC Animator Layer Control でWeightを1へ上げる形にした。

ダンスしていないなら、そもそもそのLayerが姿勢へ影響しないようにする。

修正後、問題を見ていた比較では29°のずれが0.0°になった。

「終了したら全部戻す」をやめた

修正では、ダンスの終了理由を分けた。

標準Emote / AFK

検知したフレームで、TrackingとWeightの主導権を標準側へ渡す。

MagiDanceはすぐに「正しい値を書き戻す」のではなく、一度手を離す。

ただし安全策として、状態が通常へ戻って12秒たってもTrackingが復帰していなければMagiDance側で戻す。

Sitting

座っている間は、VRChat標準のSitting挙動を正とした。

立った後にTrackingを戻す。

その他

通常終了など、標準Layerへ委譲する理由がないケースは従来どおりRestoreする。

結果として、

自分が管理すべき状態と、VRChat標準へ任せる状態を分けた。

テスト基準そのものも直した

途中で、テスト仕様にも問題があることが分かった。

初期基準では、

「座った後、0.5秒以内にTrackingへ戻る」

という期待を置いていた。

でも、座っている間に頭や手をどう扱うかはSitting側の責任でもある。

そこで最終的には、

「踊っていない状態で座った場合と同じ挙動になること」

を正とした。

これは数値基準を緩めたのではなく、比較対象を間違えていたので直した。

古い基準では0/5になることも記録したまま、新しい基準へ変更理由を残した。

修正後の検査

修正後は、

  • Static check: 26項目PASS(1項目は観測不可)
  • 動的4ケース × 5回PASS
  • 競合検査 C1〜C6 PASS
  • C5の姿勢ずれ: 0.0°
  • Smoke: 74 / 74
  • Play Mode: 63 / 63
  • Python: 45 / 45

まで通した。

ただし重要な未確認が残っている。

PCVR実機ではまだ確認していない。

EditorとEmulatorで構造・状態遷移を検査できても、HMDを被った実クライアント上の見た目とTrackingは別。

だから、この段階では「修正完了」ではなく、

Editor / Emulator上では合格、PCVR実機は未検証

としている。

「戻す」より「誰に任せるか」が大事だった

今回の失敗は、Tracking restoreの実装ミスというより責務分担のミスだった。

自分のLayerが触ったものを、自分で元に戻す。

一見正しい。

でもVRChatには、その瞬間に別のLayerが正しく所有している状態がある。

Sitting。

AFK。

Emote。

そこへ「通常Trackingへ戻す」を一律で適用すると、善意のRestoreが競合になる。

いまの結論は、

終了時に何を書くかではなく、終了後は誰がその値を所有するべきかを決める。

MagiDanceでは、そこを終了理由ごとに分けることにした。

PicoTowaでは、こういう「テストは通っているのに見た目が壊れている」問題も残していく。