Contents — 8 sections
VRChat向けのEditor Toolを作っていた。
最初のInstallは通る。
AnimatorもExpression Parametersも生成される。
「これならいける」と思って、同じアバターへもう一度Installした。
壊れた。
Expression ParametersからDLV_系のパラメータが7個消えた。
表示用AnimationClipを開くとCurveが0本になっていた。
一度目は正常。
二度目だけ壊れる。
生成ロジックそのものより、Assetの保存や再importの境界が怪しかった。
作っていたのは再実行される前提の導入ツール
対象はDancelaveというVRChat向けギミック。
Contact、Animator、Expression Menu / Parameters、表示用AnimationClipなどを自動生成し、選択したアバターの複製へ導入する。
元アバターは直接壊さない。
既存FXやExpressionsはコピーして追記する。
そして重要なのが、同じアバターへ何度Installしても壊れないこと。
ユーザーが一度しか押さない前提のToolではない。
だから再導入は、最初から品質要件の一部だった。
再導入すると7 ParameterとCurveが消えた
再現条件は単純だった。
- SDK同梱Robot AvatarへInstall
- 生成物を確認
- 同じAvatarへ再Install
- 同じパスへ生成物を作り直す
- Asset Databaseから再import
- 構造を再検査
症状は、
- Expression ParametersからDLV_系7個が消える
- Sender / Marker / Dance Effect用AnimationClipのCurveが0本になる
というもの。
厄介なのは、生成直後のメモリ上のObjectだけを見ると正常に見えることだった。
一度ディスクから読み直すと壊れる。
普通の「作った直後にassert」だけでは見逃せる。
原因はCreateAssetの順序だった
旧フローはだいたいこうだった。
- 空のAssetを作る
CreateAssetで先にディスクへ置く- その後で中身を書き換える
- 別のAsset操作やimportが走る
この順番だと、ディスク上には一度「空のAsset」が存在する。
再導入では、直前に同じ生成フォルダを削除し、同じパスへ作り直す。
その条件で後続importが走ると、ディスク上の空状態が読み直され、メモリ上で書き込んだ内容が失われた。
つまり問題は、
Unity Objectを変更したことと、その状態がAssetとして永続化されたことを同じだと思っていたこと
だった。
新規Assetは中身を完成させてからCreateAsset
修正は大掛かりではなかった。
新規Assetは、
旧:
CreateAsset
↓
中身を書き込む
ではなく、
新:
中身を完成させる
↓
CreateAsset
へ変更。
既存Assetは変更後、必要なタイミングで即保存するようにした。
さらにテスト側も変えた。
生成直後のObjectをそのまま検査するのではなく、
ディスクから再importしてから検査する。
ここが一番重要だった。
修正前は3件FAIL、修正後は56/56
スモーク試験は、SDK同梱Robot Avatarに対して、
- Build Shared Assetsを2回
- 重複がないことを確認
- 導入前Validation
- Install
- 導入後Validation
- 同じAvatarへ再Install
- 生成物をディスクから再import
- 構造を検査
まで通す。
検査対象は、
- Contact値
- localOnly
- allowSelf / allowOthers
- Animator Layer
- Tracking / Weight
- Driver
- Expressions
- Blueprint ID
- AnimationClip内Path / Curve
- 再導入後の重複
- Write Defaultsの整合
など。
修正前のコードへ同じ試験を当てると3件FAIL。
修正後は56 / 56 PASS。
「直った気がする」ではなく、壊れる旧コードでテストが落ちることまで確認した。
Editorで通っても、購入者環境で通るとは限らない
その後、もう一段階進めた。
開発Projectには、
- テストコード
- 開発用Package
- 過去の生成物
- 依存Asset
- 手元だけの設定
がある。
そこで、VRChat SDKだけの新しいProjectを作り、配布物と同じ中身だけを入れた。
結果は、
- Compile Error 0
- Smoke 68 / 68 PASS
さらに、Exporterで実際に書き出した Dancelave_v0.1.0.unitypackage を通常のimport経路で入れ直した。
配布物は33 files、54,876 bytes。
この状態でも68 / 68 PASS。
ここまで分けて初めて、
- 開発Projectで動く
- 再導入しても壊れない
- 配布物だけでも動く
- 実際のPackageをimportしても動く
を別々に確認できた。
一度作れたかより、二度作っても同じか
この件で一番大きかったのは、Idempotencyだった。
Editor Toolは「生成できるか」だけでは足りない。
- 再生成
- 再導入
- 再import
- 新規Project
- 配布Package
まで通して初めて、実運用に耐える。
特にAsset生成では、
メモリ上のObjectとディスク上のAssetを分けて考える。
これはVRChat固有というより、Unity Editor Tool全般で効く話だった。
いまの結論
派手なギミックの不具合ではない。
ダンスが暴走したわけでもない。
原因は、かなり地味なAsset保存順序だった。
でも、こういう地味な不具合ほど販売後に踏むと重い。
一度目だけ通るToolより、二度目でも、別Projectでも、Package経由でも同じ結果になるToolの方が価値がある。
PicoTowaでは、完成画面だけでなく、こういう「二度目で壊れた」話も残していく。