MRが楽しい

MRやVRについて学習したことを書き残す

MRTK v2のドキュメントを少しずつ読み解く サービス

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200329222847j:plain

複合現実の機能を実現するもの

MonoBehaviour クラスのパフォーマンスオーバーヘッドを回避するには、全てのサービスを IMixedRealityService および MixedRealityToolkit に登録します。
サービスとは、複合現実ソリューションで独立した操作を必要とするシステム、機能、またはモジュールです。
例えば、入力、境界、空間認識の機能があります。

MixedRealityToolkit はサービス間のすべての参照を調整し、それらが全ての適切なイベントを確実に受信するようにします。
これにより、必要に応じて他のサービスの検索を容易にします。
イベントには Awake、Initialize、Update、Destroy などがあります。

MixedRealityToolkit は実行中のプロジェクトで、使用中のアクティブな VR / XR / AR の SDK も維持します。
接続されたハードウェアに基づいてアクティブなデバイスを初期化し、適切な操作を開始します。

サービス

個々のサービスは、プロジェクトに実装する任意の機能です。
いくつかのプロジェクトはシーン内のシングルトンを使用しますが、このパターンには長所と短所があります。

このパターンから脱却して、従来のシングルトン実装よりもいくつかの利点をもたらすハイブリッドアプローチを採用しました。

パフォーマンス

MonoBehaviour のオーバーヘッドがない場合、スクリプトの更新は約80%速くなり、GameObject がシーンに存在する必要はありません。
blogs.unity3d.com

参照機能

サービスはシーン内の GameObjects を検索したり、FindObjectsOfType を使用するよりもはるかに速く簡単に検出できます。

タイプの依存関係なし

依存性注入と同様の方法ですが、サービスはそのタイプから分離できます。
つまり、具体的な実装は、それを利用するコードに悪影響を与えることなくいつでも交換できます。
例えば各インターフェースを完全に実装すれば、デフォルトの InputSystem をカスタムのものに置き換えることができます。

マルチシーンでの使用

サービスがシーン内のトランスフォーム位置を知る必要がある場合、サービスにアタッチされたコンポーネントではなく、シンプルに GameObject を参照または作成できます。
これにより、プロジェクトが複数のシーンにまたがる場合に、サービスを簡単に見つけて使用できるようになります。

サービスインタフェース

サービスコンテナは、サービスの保存と取得に事前定義されたインターフェイスタイプを使用します。
これにより、Mixed Reality Toolkit 内に依存関係がなくなり、各サブシステムを別のサブシステムに簡単に交換できます。
ただし、インターフェイスに準拠している必要があります。

Mixed Reality Toolkit が提供する現在のシステムインターフェースは以下のとおりです。
IMixedRealityInputSystem
IMixedRealityBoundarySystem
IMixedRealityTeleportSystem

これらのシステムの独自実装を作成する場合、Mixed Reality Toolkit によって提供されるインターフェースに準拠していることを確認する必要があります。
例えば、InputSystem を別の独自の設計に置き換える場合など。

注意

全てのサービスは、BaseServiceクラス を継承するか、IMixedRealityService を実装して、ライフサイクルが適切に処理されるように MixedRealityToolkit に必要な機能を実装する必要もあります。
例えば、Initialize、Update、Destroy は正しく呼び出される必要があります。

MRTK v2のドキュメントを少しずつ読み解く MRTK標準シェーダー その5

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200328095324j:plain

追加機能のドキュメント

以下は、MRTK/Standard シェーダーで利用可能ないくつかの機能の詳細です。

プリミティブクリッピング

パフォーマンスの高い平面、球、およびボックスシェイプのクリッピングです。
プリミティブのどちら側(内側または外側)をクリッピングするかを指定する機能を備えています。

クリッピングプリミティブの使用法を示すシーンは、MixedRealityToolkit.Examples/Demos/StandardShader/Scenes の ClippingExamples シーンにあります。
f:id:bluebirdofoz:20200328095359j:plain

ClippingPlane.cs、ClippingSphere.cs および ClippingBox.cs を使用すると、クリッピングプリミティブプロパティを簡単に制御できます。
f:id:bluebirdofoz:20200328095407j:plain

メッシュのアウトライン(輪郭)

多くのメッシュアウトライン手法は、後処理の手法を使用して行われます。
これは素晴らしい品質のアウトラインを提供しますが、多くのMixed Realityデバイスでは高コストとなる可能性があります。

メッシュアウトラインの使用法を示すシーンは、MixedRealityToolkit.Examples/Demos/StandardShader/Scenes の OutlineExamples シーンにあります。
f:id:bluebirdofoz:20200328095415j:plain

MeshOutline.cs および MeshOutlineHierarchy.cs を使用して、メッシュレンダラーの周囲にアウトラインをレンダリングできます。
このコンポーネントを有効にすると、アウトライン化されているオブジェクトの追加のレンダーパスが導入されます。
これは Mixed Reality デバイス上で高パフォーマンスで実行するように設計されており、ポストプロセスを利用しません。
この効果の制限として、閉じられていない(または両面である必要がある)オブジェクトではうまく機能せず、重なり合うオブジェクトで深度ソートの問題が発生する可能性があります。

アウトライン動作は、MRTK/Standard シェーダーと組み合わせて使用するように設計されています。
アウトラインマテリアルは通常、無地の色ですが、さまざまな効果を実現するように構成することもできます。

アウトラインマテリアルのデフォルトの構成は次のとおりです。
f:id:bluebirdofoz:20200328095425j:plain

1.Depth Write

アウトラインマテリアルでは無効にして、アウトラインが他のオブジェクトのレンダリングを妨げないようにする必要があります。

2.Vertex Extrusion

アウトラインをレンダリングするために有効にする必要があります。

3.Use Smooth Normals

この設定は、一部のメッシュではオプションです。押し出しは頂点法線に沿って頂点を移動することによって行われます。
デフォルトの法線に沿って押し出される一部のメッシュではアウトラインに不連続性が生じます。
これらの不連続性を修正するには、このボックスをチェックして、MeshSmoother.cs によって生成される平滑化された法線の別のセットを使用します。

MeshSmoother.cs はメッシュ上にスムーズな法線を自動的に生成するために使用できるコンポーネントです。
この方法では空間内の同じ位置を共有するメッシュ内の頂点をグループ化し、それらの頂点の法線を平均化します。
このプロセスは、基礎となるメッシュのコピーを作成するため、必要な場合にのみ使用される必要があります。
f:id:bluebirdofoz:20200328095433j:plain

1

MeshSmoother.csで生成されたスムーズな法線の例です。

2

デフォルトの法線が使用された状態です。キューブのコーナーの周りの現象に注目してください。

ステンシルテスト

構成可能なステンシルテストサポートが組み込まれているため、さまざまな効果を実現できます。
f:id:bluebirdofoz:20200328095443j:plain

インスタンス化された色のサポート

数千のGPUインスタンス化メッシュに固有のマテリアルプロパティを提供します。

トリプラナーマッピング

トリプラナーマッピングは、プログラムでメッシュにテクスチャを付けるテクニックです。
地形、UVなしのメッシュ、または形状の展開が難しい場合によく使用されます。
この実装は、ワールドまたはローカル空間の投影、ブレンドの滑らかさ、および法線マップのサポートをサポートしています。
使用する各テクスチャには3つのテクスチャサンプルが必要なのでパフォーマンスが重要な状況では控えめに使用してください。
f:id:bluebirdofoz:20200328095459j:plain

頂点押し出し

ワールド空間での頂点押し出しです。
押し出された境界ボリュームまたはメッシュの出入りの遷移を視覚化するのに役立ちます。
f:id:bluebirdofoz:20200328095508j:plain

その他

アルベド最適化を制御するためのチェックボックスがあります。
アルベドテクスチャが指定されていない場合、最適化アルベド操作は無効になります。
これは、リモートテクスチャロードの制御に役立ちます。
f:id:bluebirdofoz:20200328095520j:plain

ピクセル単位のクリッピングテクスチャ、ローカルエッジベースのアンチエイリアシング、および法線マップのスケーリングがサポートされています。

MRTK v2のドキュメントを少しずつ読み解く MRTK標準シェーダー その4

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200327082840j:plain

テクスチャコンバイナ

メタリック、滑らかさ、エミッション、およびオクルージョンの値はすべて、チャンネルパッキングを介して制御できます。
wiki.polycount.com

チャンネルパッキングを使用すると、4つの個別のテクスチャではなく、1つのテクスチャをサンプリングしてメモリに読み込むだけで済みます。
SubstancePhotoshop などのプログラムでテクスチャマップを作成する場合は、次のようにハンドパックできます。

チャンネル対応
Red メタリック(Metallic)
Green オクルージョン(Occlusion)
Blue エミッション(Emission)
Alpha 滑らかさ(Smoothness)

または、MRTKテクスチャコンバイナーツールを使用することもできます。
メニューから、Mixed Reality Toolkit -> Utilities -> Texture Combiner を選択して、以下のウィンドウを開きます。
f:id:bluebirdofoz:20200327082902j:plain

Unity/Standard シェーダーを選択し、[Autopopulate from Standard Material]をクリックすることで自動的に指定できます。
または、赤、緑、青、またはアルファチャネルごとにテクスチャ(または定数値)を手動で指定することもできます。
テクスチャの組み合わせはGPUアクセラレーションであり、入力テクスチャがCPUからアクセス可能である必要はありません。

MRTK v2のドキュメントを少しずつ読み解く MRTK標準シェーダー その3

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200326082418j:plain

パフォーマンス

MRTK/Standard シェーダーを使用する主な利点の1つは、パフォーマンスです。
これは有効な機能のみを利用するように拡張可能です。

MRTK/Standard シェーダーは Unity/Standard シェーダーと同等の描画を提供するように作成されていますが、はるかに低コストです。
シェーダーのパフォーマンスを比較する1つの簡単な方法は、GPUで実行する必要がある処理の数を確認することです。
もちろん、処理の大きさは有効な機能や他のレンダリング構成によって変動する場合があります。
それでも一般的に、MRTK/Standard シェーダーは Unity/Standard シェーダーよりもかなり小さな処理を実現します。

・Unity/Standard シェーダー統計の例
f:id:bluebirdofoz:20200326082430j:plain

・MRTK/Standard シェーダー統計の例
f:id:bluebirdofoz:20200326082440j:plain

ライティング

MRTK/Standard シェーダーは、ライティングに単純な近似を使用します。
このシェーダーは物理的な正確さとエネルギーの管理を計算しないため、迅速かつ効率的にレンダリングします。
Blinn-Phong は物理ベースのライティングに近づけるために、フレネルと画像ベースのライティングを組み合わせた主要なライティング技術です。

シェーダーは次のライティング技術をサポートしています。

Directional light(指向性ライト)

シェーダーは、シーン内の最初の Directional Light の方向、色、強度を考慮します。(有効な場合)
ダイナミックポイントライト、スポットライト、またはその他の Unity ライトは、リアルタイムライティングでは考慮されません。

Spherical harmonics(球面調和関数)

シェーダーは Light Probes を使用して、球面調和関数を使用してシーン内のライトを近似します。(有効な場合)
球面調和関数の計算は、計算コストを削減するために頂点ごとに実行されます。
docs.unity3d.com

Lightmapping(ライトマッピング)

静的ライティングの場合、シェーダーは Unity の Lightmapping システムで作成されたライトマップに従います。
ライトマップを使用するには、レンダラーを static(またはライトマップを static )としてマークするだけです。

Hover light(ホバーライト)

ホバーライトは、オブジェクトの表面近くでホバリングする「ポイントライト」を模倣する Fluent Design System の枠組みです。
遠く離れたカーソルの照明によく使用されます。
この機能は HoverLight.cs を介してホバーライトのプロパティを制御できます。

Proximity light(近接ライト)

近接ライトは、オブジェクトの表面近くでホバリングする「勾配逆点ライト」を模倣する Fluent Design Systemパ の枠組みです。
多くの場合、カーソル付近の照明に使用されます。
この機能は ProximityLight.cs を介して近接ライトのプロパティを制御できます。
一度に最大2つの近接ライトがサポートされます。

軽量のスクリプト可能なレンダリングパイプラインのサポート

MRTK には、開発者が MRTK シェーダーで Unity の Lightweight Scriptable Render Pipeline(LWRP)を利用できるようにするアップグレードパスが含まれています。
Unity 2019.1.1f1 および Lightweight RP 5.7.2 パッケージでテスト済みです。
LWRP の使用を開始する手順については、以下のページを参照してください。
docs.unity3d.com

MRTK アップグレードを実行するには、メニューから Mixed Reality Toolkit -> Utilities -> Upgrade LightTK Render Pipeline の MRTK Standard Shader を選択します。
f:id:bluebirdofoz:20200326083105j:plain

アップグレードを実行すると、MRTK/Standard シェーダーが変更され、マゼンタ(シェーダーエラー)マテリアルが修正されます。
アップグレードが正常に行われたことを確認するには、Assets/MixedRealityToolkit/StandardAssets/Shaders/MixedRealityStandard.shader のコンソールを確認します。
Lightweight Render Pipeline で使用するためのアップグレードが行われています。

UGUIサポート

MRTK標準シェーディングシステムは、Unity に組み込まれたUIシステムで動作します。
unity_ObjectToWorld マトリックスは Graphic コンポーネントが存在するローカルトランスフォームの変換マトリックスではありません。
その親の Canvas の変換マトリックスです。

多くの MRTK/Standard シェーダーのエフェクトでは、オブジェクトスケールを知っておく必要があります。
この問題を解決するために、ScaleMeshEffect.cs はUIメッシュの構築中にスケーリング情報をUVチャネル属性に保存します。

Unity Image コンポーネントを使用する場合、ソースイメージに「None (Sprite)」を指定することをお勧めします。
これは Unity UI が余分な頂点を生成しないようにするためです。

MRTK 内の Canvas は、必要なときに ScaleMeshEffect.cs の追加を要求します
f:id:bluebirdofoz:20200326083117j:plain

MRTK v2のドキュメントを少しずつ読み解く MRTK標準シェーダー その2

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200325080129j:plain

マテリアルインスペクター

MixedRealityStandardShaderGUI.cs と呼ばれる MRTK/Standard シェーダー用のカスタムマテリアルインスペクターが存在します。
インスペクターは、ユーザーの選択に基づいてシェーダー機能を自動的に有効/無効にし、レンダリング状態を設定します。

各機能の詳細については、Unityエディターの各プロパティにカーソルを合わせてツールチップを確認してください。
f:id:bluebirdofoz:20200325080146j:plain

インスペクタの最初の部分は、マテリアルのレンダリング状態を制御します。
[Rendering Mode]と[Cull Mode]は、マテリアルをいつどのようにレンダリングするかを決定します。
MRTK/Standard シェーダーの目的は Unity/Standard シェーダーにあるレンダリングミラーリングすることです。
MRTK/Standard シェーダーには、完全なユーザー制御のための Additive レンダリングモードと Custom レンダリングモードも含まれています。


Rendering
Mode
説明
Opaque (デフォルト)透明な領域のない通常のソリッドオブジェクトに適しています。
Cutout 不透明な領域と透明な領域の間にハードエッジを持つ透明な効果を作成できます。
このモードでは半透明の領域はなく、テクスチャは100%不透明または不可視です。
これは透明度を使用して、植生などのマテリアルの形状を作成する場合に便利です。
Fade 鏡面反射ハイライトや反射を含む、透明度の値によってオブジェクトを完全にフェードアウトできます。
このモードは、オブジェクトのフェードインまたはフェードアウトをアニメーション化する場合に便利です。
反射やハイライトもフェードアウトするため、透明なプラスチックやガラスなどの現実的な透明素材のレンダリングには適していません。
Transparent 透明なプラスチックやガラスなどのリアルな透明素材のレンダリングに適しています。
このモードでは、マテリアル自体が透明度の値を取ります。
(透明度はテクスチャのアルファチャンネルとティントカラーのアルファに基づきます)
同時に、実際の透明なマテリアルの場合と同様に、反射と照明のハイライトは完全に明瞭に表示されます。
Additive 前のピクセルカラーと現在のピクセルカラーを合計する加算ブレンドモードを有効にします。
これは透明度のソートの問題を回避するために推奨される透明度モードです。
Custom レンダリングモードのあらゆる機能を手動で制御できます。
高度な使用ケースでのみ利用します。
f:id:bluebirdofoz:20200325080157j:plain

Cull
Mode
説明
Off フェイスカリングを無効にします。
両面メッシュが必要な場合にのみ Off に設定する必要があります。
Front 前面のカリングを有効にします。
Back (デフォルト)背面のカリングを有効にします。
レンダリングパフォーマンスを改善するにはカリングを可能な限り有効にする必要があります。

MRTK v2のドキュメントを少しずつ読み解く MRTK標準シェーダー その1

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200324075044j:plain

MRTK標準シェーダー

MRTK標準シェーディングシステムは、Unityの標準シェーダーに似たビジュアルを実現できる単一の柔軟なシェーダーを利用します。
このシェーダーは Fluent Design System を実装し、複合現実デバイスでパフォーマンスを維持します。

サンプルシーン

シェーダーマテリアルサンプルは、MixedRealityToolkit.Examples/Demos/StandardShader/Scenes 配下の MaterialGallery シーンにあります。
本シーンを利用するには Examples パッケージをインポートする必要があります。
このシーンのすべてのマテリアルは、MRTK / Standardシェーダーを使用しています。
f:id:bluebirdofoz:20200324075100j:plain

MixedRealityToolkit.Examples/Demos/StandardShader/Scenes 配下には更に StandardMaterialComparison シーンがあります。
これは MRTK/Standard シェーダーと Unity/Standard シェーダーのサンプルを比較およびテストすることができます。
f:id:bluebirdofoz:20200324075109j:plain

アーキテクチャ

MRTK標準シェーディングシステムは Unity のシェーダープログラムバリアント機能を使用して、マテリアルプロパティに基づいて最適なシェーダーコードを自動生成する「uber shader」です。
ユーザーがマテリアルインスペクターでマテリアルプロパティを選択すると、有効にした機能のパフォーマンスコストのみが発生します。

MRTK v2のドキュメントを少しずつ読み解く マテリアルインスタンス

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200323030413j:plain

マテリアルインスタンス

MaterialInstance の動作は、インスタンスマテリアルの有効期間を追跡し、ユーザーのインスタンス化されたマテリアルを自動的に破棄します。
このユーティリティコンポーネントは Renderer.material または Renderer.materials の代わりとして使用できます。

MaterialPropertyBlocksはマテリアルのインスタンス化よりも優先されますが、全てのシナリオで常に使用できるとは限りません。

Renderer.material を使用することが問題になるのは何故か。
以下のコードをUnityシーンに追加してプレイを実行すると、メモリ使用量が上昇し続けます。

public class Leak : MonoBehaviour
{
    private void Update()
    {
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        // Memory leak, the material allocated is not tracked & destroyed.
        // メモリリーク。割り当てられたマテリアルは追跡および破棄されません。
        cube.GetComponent<Renderer>().material.color = Color.red;
        ...
        Destroy(cube);
    }
}

このリーク動作は、実行時間が長すぎるとUnityをクラッシュさせます!

別の方法として、MaterialInstance 動作を使用してみてください。

public class NoLeak : MonoBehaviour
{
    private void Update()
    {
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        // No memory leak, the material allocated is tracked & destroyed by MaterialInstance.
        // メモリリークはありません。割り当てられたマテリアルは、MaterialInstanceによって追跡および破棄されます。
        cube.EnsureComponent<MaterialInstance>().Material.color = Color.red;
        ...
        Destroy(cube);
    }
}

使用法

Unity の Renderer.material(s) を呼び出すと、Unity は新しいマテリアルを自動的にインスタンス化します。
マテリアルが不要になったとき、またはゲームオブジェクトが破棄されたとき、マテリアルを破棄するのは呼び出し側の作業です。
MaterialInstance の動作は、マテリアルリークの回避に役立ち、編集時および実行時のマテリアル割り当てパスの一貫性を維持します。

MaterialPropertyBlock を使用できず、マテリアルをインスタンス化する必要がある場合、MaterialInstance は次のように使用できます。

public class MyBehaviour : MonoBehaviour
{
    // Assigned via the inspector.
    // インスペクターを介して割り当てられます。
    public Renderer targetRenderer;

    private void OnEnable()
    {
        Material material = targetRenderer.EnsureComponent<MaterialInstance>().Material;
        material.color = Color.red;
        // ...
    }
}

f:id:bluebirdofoz:20200323030431j:plain

複数のオブジェクトがマテリアルインスタンスを必要とする場合、参照追跡のために明示的な所有権を取得するのが最善です。
所有権を支援するために、IMaterialInstanceOwner と呼ばれるオプションのインターフェースが存在します。

以下は使用例です。

public class MyBehaviour : MonoBehaviour,  IMaterialInstanceOwner
{
    // Assigned via the inspector.
    // インスペクターを介して割り当てられます。
    public Renderer targetRenderer;

    private void OnEnable()
    {
        Material material = targetRenderer.EnsureComponent<MaterialInstance>().AcquireMaterial(this);
        material.color = Color.red;
        // ...
    }

    private void OnDisable()
    {
        targetRenderer.GetComponent<MaterialInstance>()?.ReleaseMaterial(this);
    }

    public void OnMaterialChanged(MaterialInstance materialInstance)
    {
        // Optional method for when materials change outside of the MaterialInstance.
        // マテリアルがMaterialInstanceの外部で変更される場合のオプションメソッド。
        // ...
    }
}

f:id:bluebirdofoz:20200323030441j:plain