夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Unityエディタ拡張を使用して現在開かれているシーンのすべてのMeshRendererから使用しているShaderベースでCastShadowを設定する

本日はUnity枠です。

昨日エディタ拡張を使用して現在開かれているシーンのすべてのMeshRendererから一斉にCastShadowをオンオフすることができる機能を作りました。

redhologerbera.hatenablog.com

これは特にHoloLensなどのような影の描画を必要としないデバイスの場合描画回りの最適化として非常に有効です。 一斉に設定できることは場合によっては非常に時短になりますが、中には一部のオブジェクトのみCastShadowを使用したいorしたくないということもあります。

今回は使用しているシェーダーベースでオンオフを指定できるようにします。

〇シェーダーベースで判別する

昨日紹介したMeshRendererShadowCastingEditorでは主に①エディタウィンドウを開く ②ウィンドウに表示されるUI ③実際の処理の3つのメソッドで構成されています。

using UnityEditor;
using UnityEngine;

    public class MeshRendererShadowCastingEditor : EditorWindow
    {
        [MenuItem("Tools/Mesh Renderer Shadow Casting Editor")]
        public static void ShowWindow()
        {
         //ウィンドウを開く
        }

         //ウィンドウに表示されるUI
        private void OnGUI()
        {
        }
       //実際の処理
        private void UpdateCastShadows()
        {
           
        }
    }

この中で今回操作する必要があるのは③のUpdateCastShadows()メソッドになります。

実際のUpdateCastShadows()メソッドの中身は以下になります。

        private void UpdateCastShadows( bool castShadows)
        {
           //シーン上に存在するすべてのMeshRendererを取得します。
            MeshRenderer[] renderers = FindObjectsOfType<MeshRenderer>();

          
           //取得したRendererごとにUI上に表示されているBool型のcastShadowsの設定に基づいてオンオフを変更しています。
            foreach (MeshRenderer renderer in renderers)
            {
                    renderer.shadowCastingMode = castShadows
                        ? UnityEngine.Rendering.ShadowCastingMode.On
                        : UnityEngine.Rendering.ShadowCastingMode.Off;
            }
        }

さらに中身を開設すると実際にCastShadowのオンオフを行っているのはforeach 分内になります。

この中ではシーン内のすべてのMeshRendererについて実行されており、foreach分の処理の中でShaderによる判別を行えばよいことになります。

次のようにforeach分内でif文で今実行されているMeshRendererについてシェーダー名を取得し別で宣言するstring shadereNameと一致する場合のみcastShadowの処理が行われるようにします。

     foreach (MeshRenderer renderer in renderers)
            {
                if (renderer.sharedMaterial.shader.name == shaderName)
                {
                    renderer.shadowCastingMode = castShadows
                        ? UnityEngine.Rendering.ShadowCastingMode.On
                        : UnityEngine.Rendering.ShadowCastingMode.Off;
                }
            }

またprivate string shaderName = "Shader Name"; を追加します。

ShaerNameはUnityのエディタウィンドウ上でGUIとして表示され、編集が可能なようにしたいので UpdateCastShadows改めUpdateCastShadowsForShaderメソッドの引数にstring型でshaderNameを渡せるようにします。

        private void UpdateCastShadowsForShader(string shaderName, bool castShadows)
        {
            MeshRenderer[] renderers = FindObjectsOfType<MeshRenderer>();

            foreach (MeshRenderer renderer in renderers)
            {
                if (renderer.sharedMaterial.shader.name == shaderName)
                {
                    renderer.shadowCastingMode = castShadows
                        ? UnityEngine.Rendering.ShadowCastingMode.On
                        : UnityEngine.Rendering.ShadowCastingMode.Off;
                }
            }
        }

 最後にOnGUI上にシェーダー名を記述できるようにshaderNameのプロパティを追加します。

        private void OnGUI()
        {
            shaderName = EditorGUILayout.TextField("Shader Name", shaderName);
            castShadows = EditorGUILayout.Toggle("Cast Shadows", castShadows);

            if (GUILayout.Button("Update"))
            {
                UpdateCastShadowsForShader(shaderName, castShadows);
            }
        }

以上で完成しました。 ウィンドウを開くと次のようにシェーダー名を入力でき、シェーダーベースでCastShadowのオンオフが可能になりました。

本日は以上です。

〇コード

using UnityEditor;
using UnityEngine;

namespace ImaCreate.GraphicsTools.Editor
{
    /// <summary>
    /// This class allows you to simultaneously turn on and off the CastShadow functionality for game objects using a particular shader in the currently open scene.
    /// </summary>
    public class MeshRendererShadowCastingEditor : EditorWindow
    {
        private string shaderName = "Shader Name"; // search Shader Name
        private bool castShadows = false; // ChastShadow Settings 

        [MenuItem("Tools/Mesh Renderer Shadow Casting Editor")]
        public static void ShowWindow()
        {
            GetWindow<MeshRendererShadowCastingEditor>("Mesh Renderer Shadow Casting Editor");
        }

        private void OnGUI()
        {
            shaderName = EditorGUILayout.TextField("Shader Name", shaderName);
            castShadows = EditorGUILayout.Toggle("Cast Shadows", castShadows);

            if (GUILayout.Button("Update"))
            {
                UpdateCastShadowsForShader(shaderName, castShadows);
            }
        }

        private void UpdateCastShadowsForShader(string shaderName, bool castShadows)
        {
            MeshRenderer[] renderers = FindObjectsOfType<MeshRenderer>();

            foreach (MeshRenderer renderer in renderers)
            {
                if (renderer.sharedMaterial.shader.name == shaderName)
                {
                    renderer.shadowCastingMode = castShadows
                        ? UnityEngine.Rendering.ShadowCastingMode.On
                        : UnityEngine.Rendering.ShadowCastingMode.Off;
                }
            }
        }
    }
}