VRCQuestTools 2.3.0 あとがき
VRCQuestTools 2.3.0 をリリースしました。例によってあとがきです。
非破壊的な変換
今回の新機能で一番大きかったのはやはりNDMFでの非破壊変換でしょう。2.0.0で変換設定をコンポーネントとして保存できるようにしたことで実現可能な下地は整っていたのですが、なにぶん基礎部分の作りが古く(3年以上前!)そのままNDMFに載せるだけではうまく機能しなかったり、私事と作業時間の塩梅を調整したりとで時間がかかってしまいました。
NDMFでのビルド中に生成したアセットの扱い
そもそもVRCQuestToolsは変換の必要なアセットを複製することで元のアセットに影響を与えないという、ある意味で「非破壊」なツールでした。この一連の処理をNDMFでのビルド中に実行すればよいと当初は安易に考えていたのですが、そうはいきませんでした。
おそらくは高速化のためだと思いますが、NDMFのビルド開始時にAssetDatabase.StartAssetEditing()が呼ばれており、ビルド中にAssetsフォルダに新しくファイルを作成してもビルド完了までインポートされないようになっています。これはVRCQuestToolsで生成したpngがインポートされなかったり、Animator Controllerの複製に支障があり、結果としてアセットの取り扱いを一通り見直す必要がありました。
特にAnimator Controllerはきちんとコピーを作らないと元のAnimator Controllerの内部を参照してしまうなど何かと問題が起きやすく、2.3.0の実装では案の定バグが入っていました。2.3.1で修正し、特にFaceEmoとの相性を改善できました。アセットの複製周りは、ただでさえ分からないUnityを今よりもわかっていない頃に作った部分だったので良い機会でした。
VRCSDKの検証を回避してアバターをアップロードする
非破壊改変の常として、ビルドをするまでアバターのパフォーマンスランクや実際に使うアセットが決まらないという特徴があります。実質無制限であるPCアバターでは特に問題になりませんが、Android向けにアップロードする場合はシーン上でアップロード基準(シェーダーとコンポーネント)を満たしていない扱いになりアップロードを開始すること自体ができません。
結果として、専用のアップロードツールを作り通常とは異なる操作でアップロードをする形になりました。実装としてはVRCSDK 3.3.0で追加されたPublic SDK APIを使用してアップロードしています。
実装のとっかかりとしてはUpload without pre-checkを参考にしつつ、PC向けにAndroidビルドしたいなど独自な要件があったので結局は独自なウィンドウとなりました。(余談ですが、私は普段の改変ではオフラインテスト機能でアバターをテストしているのでQuest実機でのテストをほとんどしません。VQT Avatar Builderのボタンの並びはこのワークフローのためにあります。)
フォールバックの有効化
すっかり忘れていた機能としてフォールバック有効化がありましたが、バグ修正版の2.3.1では実装を見送りました。
フォールバック有効化の機能自体は特に難しいこともなく実装できたのですが、どうやらサーバー側でパフォーマンスランクのチェックをしているわけではないらしく、全く要件を満たしていないVery Poorのアバターでもフォールバック扱いできてしまうようです (さすがに実際にフォールバックとしては機能しないと思います)。VRCSDKだけでも同じ状況は作り出せるのですが、それはそれとして不用意なフォールバック化をできないように一工夫要りそうだという状況です。
PhysBoneのネットワークIDを一致させる
PC-Android間のPhysBoneの同期は正直非常に面倒なものでした。ネットワークIDの存在を知っていても作業を忘れがちですし。
結局何が問題なのかというと、VRCSDKが自動で割り当てるIDはアバター内での連番であるために、Android向けにPhysBoneを減らすとその分だけIDがずれてしまうことです。変換前にあらかじめ手動で割り当てれば問題ありませんが、衣装の着せ替えなどでPhysBoneが増えると同じ問題が起きます。そこで、VRCSDKとは違う手法でネットワークIDを割り当てることにしました。
PhysBoneのヒエラルキーパスの文字列からハッシュ値を計算するということは、PC-Android間でヒエラルキーパスが一致していれば同じハッシュ値が得られるということになります。このハッシュ値をもとにしてIDを割り当てれば、同じヒエラルキーパスのPhysBoneにはほぼ常に同じIDを割り当てることができ同期をとれるというわけです。NDMFのおかげで、改変をして構成が変わっても忘れずにIDを割り当てることもできるようになりました。
おわりに
ひとまず2.0.0の時点で思い描いていた機能は概ね搭載できたと思っており、しばらくは別のことができそうです。同じことだけやっていると疲れてしまいますからね。次のプロジェクトも出来上がったらあとがきを書くかもしれません。