MRが楽しい

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

MixedRealityToolkit/StandardShaderのテクスチャを動的に切り替えた時にInspectorを開いたときのみ反映される問題の対処

本日は MRTK の小ネタ枠です。
MixedRealityToolkit/StandardShaderのテクスチャを動的に切り替えた時にInspectorを開いたときのみ反映される問題の対処を記事にします。
f:id:bluebirdofoz:20210531212756j:plain

問題事象

以下のようにテクスチャが設定されていない MixedRealityToolkit/StandardShader のマテリアルを持つオブジェクトを用意します。
f:id:bluebirdofoz:20210531212809j:plain

次にスクリプトを用意し、ボタンを押下したときに指定のテクスチャをマテリアルに反映してみます。
・TextureChangeTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TextureChangeTest : MonoBehaviour
{
    [SerializeField, Tooltip("変更テクスチャ")]
    private Texture2D changeTexture;

    private MeshRenderer meshRenderer;

    public void ChangeTexture()
    {
        // 確認用ログ
        Debug.Log("ChangeTexture");

        // メッシュレンダラーの参照を取得する
        meshRenderer = this.GetComponent<MeshRenderer>();

        // マテリアルのテクスチャを変更する
        meshRenderer.material.SetTexture("_MainTex", changeTexture);
    }
}

f:id:bluebirdofoz:20210531212822j:plain

試しにシーンを再生してみます。
f:id:bluebirdofoz:20210531212833j:plain

ボタンを押下して、関数が実行されてもテクスチャが反映されません。
f:id:bluebirdofoz:20210531212843j:plain

しかし、対象オブジェクトの Inspector からマテリアルの情報を開くと、このタイミングでテクスチャが反映されて表示されるという事象が発生します。
f:id:bluebirdofoz:20210531212854j:plain

この事象は HoloLens 上でも再現します。
ただし HoloLens で発生した場合は Inspector を開いたりはできないため、ボタンを押下してもテクスチャが反映されることはありません。
f:id:bluebirdofoz:20210531212908j:plain

問題の解決方法 その1

(2021/5/31 解決方法 その1 を追記)
問題を解決するにはテクスチャの動的差し替えを行う MixedRealityToolkit/StandardShader のマテリアルに[Assigned at Runtime]のチェックを入れておきます。
f:id:bluebirdofoz:20210531220953j:plain

同じようにオブジェクトにスクリプトを追加し、ボタンを押下したときに設定したテクスチャをマテリアルに反映してみます。
f:id:bluebirdofoz:20210531221005j:plain

シーンを再生してみます。
f:id:bluebirdofoz:20210531221016j:plain

ボタンを押下すると即座にテクスチャが反映されました。
f:id:bluebirdofoz:20210531221030j:plain

こちらの設定であれば HoloLens 上でも正常に動作します。
ボタンを押下するとテクスチャが即座に反映されます。
f:id:bluebirdofoz:20210531221045j:plain

問題の解決方法 その2

または問題を解決するには MixedRealityToolkit/StandardShader のマテリアルを再作成して、マテリアルの参照を差し替えます。
以下のようにマテリアルの差し替えを行うスクリプトを作成しました。
1.MixedRealityToolkit/StandardShader から新規マテリアルのインスタンスを作成する
2.変更前のマテリアルの情報を新規マテリアルに引き継ぐ
3.新規マテリアルにテクスチャを設定する
4.マテリアルの参照を差し替え
・MaterialChangeTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MaterialChangeTest : MonoBehaviour
{
    [SerializeField, Tooltip("ベースシェーダ")]
    private Shader baseShader;

    [SerializeField, Tooltip("変更テクスチャ")]
    private Texture2D changeTexture;

    private MeshRenderer meshRenderer;

    public void ChangeMaterial()
    {
        // 確認用ログ
        Debug.Log("ChangeMaterial");

        // メッシュレンダラーの参照を取得する
        meshRenderer = this.GetComponent<MeshRenderer>();

        // 指定 Shader から新規マテリアルのインスタンスを作成する
        Material initializeMaterial = new Material(baseShader);

        // 変更前のマテリアルの情報を新規マテリアルに引き継ぐ
        initializeMaterial.SetColor("_Color", meshRenderer.material.color);

        // 新規マテリアルにテクスチャを設定する
        initializeMaterial.SetTexture("_MainTex", changeTexture);

        // マテリアルの参照を差し替え
        meshRenderer.material = initializeMaterial;
    }
}

f:id:bluebirdofoz:20210531212922j:plain

ベースとなるシェーダには MixedRealityToolkit/StandardShader の参照を設定しています。
f:id:bluebirdofoz:20210531212938j:plain

シーンを再生してみます。
f:id:bluebirdofoz:20210531212957j:plain

ボタンを押下するとテクスチャが反映されたマテリアルに即座に切り替わりました。
f:id:bluebirdofoz:20210531213009j:plain

こちらのスクリプトは HoloLens 上でも正常に動作します。
ボタンを押下するとテクスチャが即座に反映されます。
f:id:bluebirdofoz:20210531213020j:plain

事象の原因

2021/05/31 現在、私には分かっていません。
解決方法 その1にある通り、マテリアルの設定で解決できることから、以下の記事のシェーダバリアントに起因する事象と同じ原因である可能性が高いです。
ただし、コードを確認しても原因がシェーダバリアントによる無効化とは確認できませんでした。
bluebirdofoz.hatenablog.com

その他

テクスチャ設定済みのMixedRealityToolkit/StandardShader

本事象はテクスチャが設定されていない MixedRealityToolkit/StandardShader のマテリアルでのみ発生します。
以下のように予め別のテクスチャが設定されたマテリアルに対し、テクスチャ差し替えのみ行う1つめのスクリプトを試してみます。
f:id:bluebirdofoz:20210531213041j:plain

シーンを再生してみます。
f:id:bluebirdofoz:20210531213053j:plain

ボタンを押下するとテクスチャが即座に切り替わりました。
f:id:bluebirdofoz:20210531213104j:plain

こちらのパターンは HoloLens 上でも正常に動作します。
f:id:bluebirdofoz:20210531213115j:plain

Unity/Standard

また Unty/Standard シェーダ利用時は本事象は発生しません。
以下のようにテクスチャが設定されていない Unity/Standard マテリアルに対し、テクスチャ差し替えのみ行う1つめのスクリプトを試してみます。
f:id:bluebirdofoz:20210531213127j:plain

シーンを再生してみます。
f:id:bluebirdofoz:20210531213147j:plain

ボタンを押下するとテクスチャが即座に切り替わりました。
f:id:bluebirdofoz:20210531213158j:plain

本パターンも HoloLens 上で正常に動作します。
f:id:bluebirdofoz:20210531213208j:plain