見出し画像

VRCQuestTools 2.0.0/2.1.0 あとがき

VRCQuestTools 2.0.0 および 2.1.0 をリリースしました。2年と少しぶりの大きな変更だったので、Xのポストでは書ききれないようなポイントなどをざっくり思いつくままにまとめておきます。あとがきなので細かいことは考えず無軌道です。


2.0.0

時が経つのは早いものでVRCQuestToolsの前身となったエディタ拡張(現在非公開)から数えるともう3年半も経っています。当時はPhysBoneなどというものはなく(それどころかVRCSDK2でした)、Quest対応の自動化はシンプルなもので十分でした。概ね、当時nyantelさんが公開されていたQuest対応手順にマテリアル複製とテクスチャ生成の手順を追加した程度のものです。そういえばこの手順書の頃ってまだUnity 2017でしたね(遠い目)。

長らく続いた1.xはそんな時代の思想で作られたツールだというのが根底にあり、VRCSDK3を前提とした複雑・高度な改変ツールや、ここ最近の(と言っても実は1年以上経ちますが)非破壊改変ワークフローの登場によって使い勝手が必ずしも良くない状況も出てきていました。
ある程度まとまった時間がとれたこと、この数年で貯まったUnityに関する知見をフィードバックして機能改善を見込める、といったところからメジャーバージョンアップとしての開発を始めました。

サポート対象のVRCSDKの変更

2.0.0からはVRCSDK 3.3.0以降をサポート対象としました。Public SDK APIの概念が登場したバージョンということでキリがよく、またUnity 2019を引き続きサポートできるためです。

Unity 2018から2019への移行の時もそうでしたが、VRCQuestToolsでは一つ前のUnityに対応する最後のVRCSDKに対して可能な限り長くサポートするようにしています。(結果、Unity 2019移行の後も1年半以上Unity 2018でも動作する状態を維持していました。)
動作テストが少し大変にはなりますが、各Unityバージョンでビルドが最低限通るかどうかと一部のユニットテストをGitHub ActionsでGameCIを使って確認しています。

メニュー階層の変更

「VRCQuestTools」メニューをメニューバー直下から「Tools」内へ移動しました。アバター改変にあたり様々なツールを入れていくとメニューバーの項目があふれかえってしまうのが前々から気になっていましたが、Modular AvatarやAvatar Optimizerが「Tools」の下に配置されているのを見て、これは良さそうだということで2.0.0のタイミングで変更することにしました。

とにかく横に長い。人によってはもっとたくさん並んでますよね?
一か所にまとまっていい感じ。

後から知ったことですが、適切な既存メニューがない場合はTools配下に置くのがよいらしく、Unity文脈的にも正解だったようです。

Avatar Converter Settings

アバターにツール独自の設定を保存するということ

今まではアバターの変換設定はその場限りのもので毎回設定のやり直しが必要でしたが、コンポーネントという形でアバターに紐づけて保存することができるようになりました。

これまでにも、アバターに対するツール独自の設定をアバター外のシーン内オブジェクトとして保存するようなエディタ拡張はありましたが、アバターのヒエラルキーだけで完結できないのでそのような形で設定を保存することを敬遠していました。最近は以下のような状況が整ってきたということで設定を保存できるようにしました。

  • VRCSDK 3.1.12で追加されたVRC.SDKBase.IEditorOnlyインターフェースを実装することで、ビルドを邪魔しない形で設定保存用の独自MonoBehaviorを実装可能になった。

  • Modular Avatar / Avatar Optimizerの普及により独自コンポーネントをアバターに付けて設定管理することが普通になった。

(あと、自分自身がアバター変換を何度もやるうちに設定を変え忘れたりPhysBoneの削減を毎回やり直すのがさすがに嫌になってきたのもあります。)

Prefab Override

使い方としてPrefabにAvatar Converter Settingsを設定して同じ設定を使い回すことを想定しているわけですが、その上でPrefab Overrideが設定されていることが分かるようになっていると便利です。

青い部分がPrefabの設定値からオーバーライド(上書き)された項目。
他のコンポーネントでも見覚えがありますよね。

カスタムのインスペクターをSerializedObjectEditorGUILayout.PropertyField()を使って実装してあげることで、Unityがいい感じに表示を制御してくれるようです。よって、インスペクターの実装ではEditorGUILayout.ObjectField()などのパラメータを直接参照するフィールドは使用しないことになります。

ノーマルマップによる影の生成

ノーマルマップを活用した衣装モデルはPCでの見栄え・質感が素晴らしいのですが、シェーダーをToon Litに変更すると、まあ残念なことになっていました。

もはや説明するまでもない。のっぺり。

ノーマルマップを活用することでのっぺりテクスチャを改善する手法を少し前に見て影響を受け、今回機能追加をがんばりました。

上の例では画像編集ソフトを駆使して実施していましたが、VRCQuestToolsではテクスチャ生成用のシェーダーを使って実際に影(のようなもの)を計算するという手法を取りました。大まかには以下のようなものです。

  1. 基本的なLambert拡散反射およびPhong鏡面反射を実装して明るさを決める。このときメッシュの情報を使用せずにノーマルマップの法線情報をそのまま使用し、光源および視線のベクトルは常に一定とする。(QuadにDirectional Lightを当て、正面から見たような状態を想定)

  2. マテリアルの影パラメーターから、変換元シェーダーでの影の付け方を大雑把にシミュレーションし最終的な色を決める。

シェーダーごとに影パラメーターの意味や色の出方が全然違うので苦労しましたが、なかなか良い結果を得られたのではないでしょうか。

(この衣装の場合は割と理想的な条件が揃っていたという見方もあります)

マテリアル変換設定

一部のマテリアルはToon Litに変換するよりもMatCap Litにした方がよいケース(アクセサリなど)や、Quest用に独自に作ったマテリアルを使いたいケースがあることは自分自身でもあったのですが、今まで手作業で乗り切っていました。今回Avatar Converter Settingsができたことで、複雑な変換設定もパラメーターとして保存する余地が生まれました。

Unity 2019からはSerializeReferenceという属性が追加されており、非UnityEngine.Objectなインターフェース型のデータをシリアライズできるようになっています。変換対象のシェーダーごとにクラスを分離して実装でき、あまり複雑なことを考えずにデータ構造を決めることができました。

[SerializeReference]
public IMaterialConvertSettings defaultMaterialConvertSettings = new ToonLitConvertSettings();

https://github.com/kurotu/VRCQuestTools/blob/v2.0.0/Packages/com.github.kurotu.vrc-quest-tools/Runtime/Components/AvatarConverterSettings.cs#L19-L20

NDMFの導入

Modular Avatar / Avatar Optimizerとの互換性確保のため、共通基盤であるNon-Destructive Modular Framework (NDMF)にVRCQuestToolsも部分的に対応しています。

VRCQuestToolsは性質上、VRCSDK以外の特定のアバター改変ツールの導入を前提にすることは望ましくありません。一方で、互換性確保のためにはそのツールの存在に依存する必要があるという矛盾があります。

そこでNDMFに関連する処理は本体とは独立した別のアセンブリ定義にまとめ、NDMFが存在するときだけビルドするように設定しました。Version DefinesとDefine Constraintsを使うことで実現できます。

Version Defines

特定のパッケージが存在するときにシンボルを定義することができます。ソースコード中で#ifを使うことで、パッケージの有無に応じて処理を切り替えることができます。VCC(VPM)になって嬉しかったことの一つです。

プロジェクトにNDMF (nadena.dev.ndmf)があるとVQT_HAS_NDMFが定義されます。

Define Constraints

シンボル定義が指定した条件を満たしているときだけ、そのアセンブリをビルドします。Version Definesと組み合わせることで、特定のパッケージが存在するときだけビルドするようなアセンブリを定義できます。

VQT_HAS_NDMFが定義されているときだけビルドします。
Version Definesで定義したシンボルも使用できます。

NDMF対応の実装

エディタ拡張を作れるのであれば、NDMFのIntroductionとExecution Modelの説明を見れば特に難しいところはないと思います。

書かれていないこととして、Plugin内で実行する処理はベタ書きするのではなくPass<T>を継承したクラスに分離すると見通しよく実装できると思います。

https://github.com/kurotu/VRCQuestTools/blob/v2.1.1/Packages/com.github.kurotu.vrc-quest-tools/Editor/NDMF/VRCQuestToolsNdmfPlugin.cs

Platform Component Remover

プラットフォームに合わせてビルド処理を切り替えるという発想はVirtualLens2のRemote Only Modeがヒントになりました。

元々はAAO Remove Mesh By BlendShapeをPC Prefabに設定してアバター間で流用したいという目的で実装したものでしたが、偶然にも実装と同時期にMantis LOD EditorのNDMF化ツールがリリースされていたことで想定以上の用途が生まれてしまっていました。元々はもう少し寝かせておくつもりでしたが、さっさと2.1.0をリリースすることにしました。

コンポーネントのヘルプURLの整備

Unityの独自コンポーネントは、HelpURL属性を付けることでインスペクターの「?」アイコンからブラウザでドキュメントを開くことができます。ドキュメントページを用意していなくても、例えばBoothのURLを設定しておくだけでも全然アリだと思います。

言語自動切り替えの実装

HelpURLは固定値なので、表示言語を自動的に切り替えたい場合はWebサイト側で言語切り替えを実装する必要があります。VRCQuestToolsのドキュメントサイトに使用しているDocusaurusには多言語対応の仕組みが元々備わっていますが、言語を自動検出して切り替えるような仕組みはありません。

そこで、Unityからページを開いた時にだけ言語検出をして適切な言語(日本語)のページにリダイレクトする仕組みを実装しました。表面的な挙動はModular Avatarを参考にしています。

https://github.com/kurotu/VRCQuestTools/blob/v2.1.1/Website/src/theme/Root.tsx

おわりに

ちょうどまとまった時間ができたことで、なかなか手を付けられずにいた箇所に手を入れることができ大きなアップデートになりました。初版以来変わらずにいた基本構造に手を入れたことで、現代の非破壊ワークフローに付いていく最低限の準備もできましたが、いくつか課題の見えている状況でどうしたものか…と考えている状況です。
作業時間・気力の確保もさることながら、非破壊でなくても自分個人の範囲だとあまり困っていないのもあり、ほどほどに期待しながら待っていただければと思います。





誰かが勝手に作ってもいいんですよ!と言いたいところですがそれほど素性のいいコードではないですね…はい…

この記事が気に入ったらサポートをしてみませんか?