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では、こういう「テストは通っているのに見た目が壊れている」問題も残していく。