VRChat アバタープロジェクト向けの、アバター単位マテリアル分離ツール。
1 つの Unity プロジェクトに複数のアバターを入れていると、Material / Texture が共有参照になっているせいで、アバター A のために調整した変更がアバター B にも勝手に反映されてしまいます。xestrel は選択したアバターの Renderer 階層を走査して:
- マテリアル: 参照されている各
MaterialをAssets/Xestrel/<アバター名>/Materials/以下のアバター専用コピーに置き換え、Renderer.sharedMaterialsを差し替えます。Isolate ボタンで一括実行されます(ボタンにはコピー対象の共有マテリアル数が表示されます)。 - テクスチャ: テクスチャプロパティ単位・オンデマンド。ウィンドウにコピー元マテリアルのテクスチャスロットが並ぶので、行ごとの Isolate ボタンでその 1 枚だけを
Assets/Xestrel/<アバター名>/Textures/にコピーして差し替えます。Isolate All Textures でマテリアル内の全スロットを一括分離もできます。分離していないテクスチャは共有元を参照したままで、分離済みスロットには Restore ボタンが出ます。 - アニメーター:
AnimatorController単位・オンデマンド。ウィンドウの Animators セクションには、まだ共有コントローラーを指しているVRCAvatarDescriptorの Playable Layer が一覧表示され、ワンクリックで Isolate できます(オブジェクトフィールドに任意のコントローラーを入れることも可能)。コントローラーはAssets/Xestrel/<アバター名>/Animators/へ、参照されているAnimationClip(ステート・サブステートマシン・ブレンドツリー)はAssets/Xestrel/<アバター名>/Animations/へコピーされ、コピー側コントローラーはクリップコピーを使うよう書き換えられます。元のコントローラーが Descriptor の Playable Layer から参照されていた場合は、その参照もコピーに差し替わります。
元のアセットには一切手を付けません。アバタールートに XestrelMaterialIsolation コンポーネントが追加され、すべての 元 → コピー の対応を記録します。VRC.SDKBase.IEditorOnly を実装しているため、VRChat アップロード時には除去されます。
Unity 2022.3 LTS、VRChat Avatars SDK 3.5+。NDMF / Modular Avatar / Avatar Optimizer との連携はありません — xestrel が触るのは Renderer.sharedMaterials だけです。
このディレクトリを Unity プロジェクトの Packages/net.yozolab.xestrel/ にコピーまたはシンボリックリンクしてください。エディタを開くと Xestrel.Runtime.dll と Xestrel.Editor.dll にコンパイルされます。
- アバタープレハブをシーンに配置します。
- Hierarchy でアバタールートを右クリック → Xestrel → Isolate Materials、または Window → Xestrel → Asset Isolation を開いて Isolate を押します。ウィンドウは Hierarchy の選択に追従してアバターを切り替えます。固定したい場合は Avatar フィールド横のロックトグルを使ってください。
- マテリアルコピーが
Assets/Xestrel/<アバター名>/Materials/に作られ、レンダラーが差し替わります。Folder ボタンで Project ウィンドウ内のそのフォルダーを表示できます。 - ウィンドウはタブ構成です: Materials(マテリアル単位のバインディング)、Textures(コピー側マテリアルが参照する全テクスチャの一覧)、Animators、Isolated(xestrel がこのアバターに行った変更の一覧 — マテリアル / テクスチャ / アニメーター / クリップに加え、どこからも参照されなくなった未使用コピーも表示)、Additions(ベース Prefab に対して何が追加されたか: 追加された Prefab インスタンスやシーンオブジェクトの一覧と追加単位の Isolate、追加 / 削除されたコンポーネント。Unpack 済みアバターでは子 Prefab インスタンスの一覧に切り替わります)、Not Isolated(まだ共有のままのアセット一覧。タブラベルに未分離数が表示されます)。
- Materials タブでバインディングを展開します。アバター専用にしたいテクスチャスロットの Isolate ボタンを押すと、そのテクスチャが
Assets/Xestrel/<アバター名>/Textures/にコピーされて差し替わります。Isolate All Textures で全スロット一括も可能。分離済みスロットは ● マーク付きで、Restore で個別に戻せます。 - Textures タブでは各テクスチャのサムネイル・分離状態・使用箇所(どのマテリアルのどのスロットか)が一覧できます。ここでの Isolate / Restore は、そのテクスチャを使う全スロットを一括で差し替え/復元します。
- Not Isolated タブには、共有のままのマテリアル(使用スロット数付き・ワンクリックで個別分離)、テクスチャ、Descriptor の Playable Layer がまとめて表示されます。
- Isolate の再実行はマテリアルに対しては no-op です。テクスチャ分離が自動で走ることはありません。
- インスペクターまたはウィンドウの Restore(確認ダイアログ付き)で、テクスチャプロパティを先に元へ戻し、その後すべてのレンダラーを共有マテリアルへ戻します。マテリアル 1 つだけ戻したい場合は Restore Material ボタンを使ってください。コピーアセットは常にディスクに残ります。
- Project ウィンドウでコピーアセットを削除した場合、ウィンドウ / インスペクターに Prune ボタンが表示され、参照切れになったバインディングを掃除できます。
Window → Xestrel → Dependencies(または分離ウィンドウの Deps ボタン)で、アバターの依存関係がインデント式のツリーで開きます。第1リングは汎用的に発見されます — 階層内の全コンポーネントのシリアライズ済みオブジェクト参照をすべて走査するため、Modular Avatar / VRCFury / オーディオ / メッシュ / メニューへの参照も型ごとの対応なしで現れます。各行の ▸ n ボタンでそのアセット自身の直接依存が展開されます(インポートパイプライン経由なので軽量)。種別トグル(Mat / Tex / Mesh / Anim / Clip / Menu / Shader / Prefab / Other)、Assets/ 外を隠す No Pkg トグル、検索ハイライトで一覧を読みやすく保てます。分離状態は行頭の色ドットです: 橙=まだ共有(隔離可能)/ 緑=隔離済みコピー / 赤=他ワークスペースのマニフェストも参照しているコピー(バッジにワークスペース名を表示。未ロードのシーンでも検出)/ グレー=xestrel の管理対象外。各行にはプライマリアバターに対する Isolate / Restore ボタンがインラインで付き、名前クリックで Ping します。Add Selected で複数のアバターをルートに追加でき、複数のアバターから参照されているアセットには ×n avatars バッジが付きます。
Assets/Xestrel/以下のフォルダ名は、アバターを最初に分離した時点で確定します。以後 GameObject をリネームしても安全で、既存・新規のコピーは元のフォルダに入り続けます(どのフォルダかはステータス行に表示されます)。- フォルダ名がすでに使われている場合(別シーンの同名アバター、コンポーネント削除後の残骸など)は
(n)サフィックスが付きます。同じプレハブを複数のシーンに置いたり、1つのシーンに2体置いたりしても、それぞれが独立したワークスペースになります。 - 編集を引き継いだ派生を作る: ウィンドウの Fork ボタンを押すと、アバターをシーン内で複製し(プレハブ接続は維持)、その場で複製側に独立コピーを持たせます。手動で複製(Ctrl+D)しても構いません: 複製直後は同じコピーアセットを共有した状態なので、ウィンドウに警告と Fork ボタンが表示されます — 複製した側で Fork を押してください。バインドされたマテリアル / テクスチャ / アニメーター / クリップがすべて新しいワークスペースフォルダに再コピーされ(それまでの編集内容ごと引き継がれます)、複製側だけがフォークに配線し直されます。各バインディングは本当の共有元を指し続けるので、Restore もアバターごとに正しく動きます。元のアバターには一切触りません。ゼロから改変を始めたい場合は、これまでどおり元のプレハブを新しく置いて分離してください。
- 各ワークスペースには、コンポーネントのバインディングを変更のたびにミラーするマニフェストアセット
Assets/Xestrel/<AvatarName>/XestrelWorkspace.assetも保存されます。正はあくまでアバター上のコンポーネントで、マニフェストはコンポーネントを失っても original → copy の対応が生き残るための保険です。 - プレハブの Revert All やシーンの事故などでコンポーネントが消えても、Renderer がコピーを参照したままであればウィンドウが検知し、マニフェストからコンポーネントを再構築する Recover ボタンを表示します。
- マニフェストは、これまでに記録されたすべての copy → original ペアの GUID 履歴を恒久的に保持します。アセットが行方不明の間に Prune されたバインディングも、後から関係を復元できます。
Assets/Xestrel/以下のワークスペースフォルダをリネームしても自動で追従します。ワークスペースは新しいフォルダ名を引き継ぎ、新規コピーも既存コピーの隣に入り続けます。- アバターのプレハブアセット自体が Xestrel コピーを参照している場合(Renderer / Descriptor のオーバーライドをプレハブに Apply した場合)、ウィンドウが警告します — その状態では、全シーンのそのプレハブの全インスタンスがコピーを使うことになります。
- マテリアルコピーは
AssetDatabase.CopyAssetで作られる素の.matアセットです(Material Variant ではありません)。元とは完全に独立します。 - テクスチャコピーも
AssetDatabase.CopyAssetを使うため、インポーター設定(圧縮・sRGB・ミップマップ等)が引き継がれます。モデルのサブアセット(FBX 埋め込みなど)やディスク上にアセットがないもの(RenderTextureなど)は警告付きでスキップされ、コピー側マテリアルの参照は元のままになります。 - アニメーターコピーも
AssetDatabase.CopyAssetを使うのでサブアセット(ステート・ブレンドツリー・トランジション)ごとコピーされ、その後 xestrel がコピーを走査してすべてのMotion参照をクリップコピーに書き換えます。FBX / モデルアセット埋め込みのクリップとAnimatorOverrideControllerは対象外です。
Runtime/— マテリアル / テクスチャ / アニメーター / クリップのバインディングを持つXestrelMaterialIsolationMonoBehavior(IEditorOnly)Editor/Core/— ログ・パスヘルパーEditor/Detection/— アバタールート解決(VRCAvatarDescriptor)Editor/Isolation/— マテリアル / テクスチャ / アニメーターのコピーファクトリと分離サービスEditor/UI/— EditorWindow + Hierarchy コンテキストメニューEditor/Inspector/— MonoBehavior 用カスタムインスペクターTests/— Editor Test Runner スイート