Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by hzigy · Aug 08, 2013 at 10:56 PM · shadersassetmaterials

Find materials that use a certain shader

As my project grows steadily in size, there are a lot of assets that are being used.

Working with so many assets, I have found that some are using the wrong shader (I found that out as some shaders were added to the build that should not be used).

I found it very time consuming tracking these rogue materials manually by checking each one for shader type. Is there a way to speed up the process? Like selecting a shader type and getting a list of all materials/objects that use this type?

Tnx a bunch

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image donnysobonny · Aug 09, 2013 at 12:46 AM 0
Share

Hmm are you wanting to search materials of objects in your assets or in the hierarchy?

If your objects are in your hierarchy, you can simply do a quick loop through all of your objects, find the materials and the shader that is used by the material. Then just build an array of materials with the shader you are looking for. Here's a rough untested example in c#:

 //find all of the objects either within the scene or from a created list of GameObjects, then run a loop for each found GameObject something like the following:
 
 string shaderToLookFor = "diffuse"; //the shader you want to find
 ArrayList<GameObject> objectsWithShader = ArrayList<GameObject>(); //the gameObjects found with the shader
 foreach(GameObject go in foundGameObjects)
 {
     if(go.renderer.material.shader.name == shaderToLookFor)
     {
         objectsWithShader.Add(go);
     }
 }

I haven't tested this but it should work.

avatar image hzigy · Aug 09, 2013 at 09:05 PM 0
Share

Your solution works well, very similar to robertbu's.

Tnx for your help

2 Replies

· Add your reply
  • Sort: 
avatar image
6
Best Answer

Answer by robertbu · Aug 09, 2013 at 04:24 AM

I did not see an easy way of finding all the material in the project, but it is straight forward to find all the materials that are in use in the project. So the following editor script will give a list of all the materials that are attached to any Renderer in a project that have the specified shader. Right now you must enter the full name. So it might be something convoluted like "Custom/unlit/old/Fringing With Transparency." You could change the comparison to a string.Contains() to do a substring match for something more forgiving. I've only lightly tested it.

 using UnityEngine;
 using UnityEditor;
 using System.Collections.Generic;
 
 public class FindShaderUse : EditorWindow {
     string st = "";
     string stArea = "Empty List";
  
     [MenuItem("Window/Find Shader Use")]
     public static void ShowWindow() {
         EditorWindow.GetWindow(typeof(FindShaderUse));
     }
  
     public void OnGUI() {
         GUILayout.Label("Enter shader to find:");
         st = GUILayout.TextField (st);
         if (GUILayout.Button("Find Materials")) {
             FindShader(st);
         }
         GUILayout.Label(stArea);
     }
     
     private void FindShader(string shaderName) {
         int count = 0;
         stArea = "Materials using shader " + shaderName+":\n\n";
         
         List<Material> armat = new List<Material>();
         
            Renderer[] arrend = (Renderer[])Resources.FindObjectsOfTypeAll(typeof(Renderer));
         foreach (Renderer rend in arrend) {
             foreach (Material mat in rend.sharedMaterials) {
                 if (!armat.Contains (mat)) {
                     armat.Add (mat);
                 }
             }
         }
         
         foreach (Material mat in armat) {
             if (mat != null && mat.shader != null && mat.shader.name != null && mat.shader.name == shaderName) {
                 stArea += ">"+mat.name + "\n";
                 count++;
             }
         }
         
         stArea += "\n"+count + " materials using shader " + shaderName + " found.";
     }
 }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image hzigy · Aug 09, 2013 at 09:03 PM 2
Share

Well i tested it for you and it works quite nice. It doesn't find all materials though - for example, it fails to find terrain materials (since it doesn't have a renderer) or materials that are assigned to a renderer only through code at runtime, but thats O$$anonymous$$ for me.

Taking your code I have expanded the solution a bit and added a toggle for exact name or string.Contains().

Tnx for your help!

     using UnityEngine;
     using UnityEditor;
     using System.Collections.Generic;
     
     public class FindShaderUse : EditorWindow
     {
         string st = "";
         string stArea = "Empty List";
         Vector2 scrollPos;
         bool exact;
     
         [$$anonymous$$enuItem("Window/Find Shader Use")]
         public static void ShowWindow()
         {
             EditorWindow.GetWindow(typeof(FindShaderUse));
         }
     
         public void OnGUI()
         {
             GUILayout.Label("Enter shader to find:");
     
             EditorGUILayout.BeginHorizontal();
             st = GUILayout.TextField(st);
             EditorGUIUtility.LookLikeControls(40);
             exact = EditorGUILayout.Toggle("Exact", exact, GUILayout.Width(60));
             EditorGUILayout.EndHorizontal();
     
             if (GUILayout.Button("Find $$anonymous$$aterials"))
             {
                 FindShader(st);
             }
     
             scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Width(position.width), GUILayout.Height(position.height-60));
             GUILayout.Label(stArea);
             EditorGUILayout.EndScrollView();        
         }
     
         private void FindShader(string shaderName)
         {
             int count = 0;
             stArea = "$$anonymous$$aterials using shader " + shaderName + ":\n\n";
     
             List<$$anonymous$$aterial> armat = new List<$$anonymous$$aterial>();
     
             Renderer[] arrend = (Renderer[])Resources.FindObjectsOfTypeAll(typeof(Renderer));
             foreach (Renderer rend in arrend)
             {
                 foreach ($$anonymous$$aterial mat in rend.shared$$anonymous$$aterials)
                 {
                     if (!armat.Contains(mat))
                     {
                         armat.Add(mat);
                     }
                 }
             }
     
             foreach ($$anonymous$$aterial mat in armat)
             {
                 if (mat != null && mat.shader != null && mat.shader.name != null)
                 {
                     if ((exact && mat.shader.name == shaderName) || (!exact && mat.shader.name.Contains(shaderName)))
                     {
                         stArea += ">" + mat.name + "\n";
                         count++;
                     }
                 }
             }
     
             stArea += "\n" + count + " materials using shader " + shaderName + " found.";
         }
     }
avatar image
6

Answer by msklywenn · Oct 24, 2016 at 11:50 AM

This works for all assets, not just the loaded ones :

 using UnityEngine;
 using UnityEditor;
 using System.Collections.Generic;
 using System.IO;
 
 public class ShaderOccurenceWindow : EditorWindow
 {
     [MenuItem("Tools/Shader Occurence")]
     public static void Open()
     {
         GetWindow<ShaderOccurenceWindow>();
     }
 
     Shader shader;
     List<string> materials = new List<string>();
     Vector2 scroll;
 
     void OnGUI()
     {
         Shader prev = shader;
         shader = EditorGUILayout.ObjectField(shader, typeof(Shader), false) as Shader;
         if (shader != prev)
         {
             string shaderPath = AssetDatabase.GetAssetPath(shader);
             string[] allMaterials = AssetDatabase.FindAssets("t:Material");
             materials.Clear();
             for (int i = 0; i < allMaterials.Length; i++)
             {
                 allMaterials[i] = AssetDatabase.GUIDToAssetPath(allMaterials[i]);
                 string[] dep = AssetDatabase.GetDependencies(allMaterials[i]);
                 if (ArrayUtility.Contains(dep, shaderPath))
                     materials.Add(allMaterials[i]);
             }
         }
 
         scroll = GUILayout.BeginScrollView(scroll);
         {
             for (int i = 0; i < materials.Count; i++)
             {
                 GUILayout.BeginHorizontal();
                 {
                     GUILayout.Label(Path.GetFileNameWithoutExtension(materials[i]));
                     GUILayout.FlexibleSpace();
                     if (GUILayout.Button("Show"))
                         EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(materials[i], typeof(Material)));
                 }
                 GUILayout.EndHorizontal();
             }
         }
         GUILayout.EndScrollView();
     }
 }

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image chrisvarnsverryvirtualarts · Nov 22, 2017 at 01:38 PM 0
Share

Doesn't work with inbuilt shaders but easy to fix, thanks!

avatar image msklywenn · Nov 22, 2017 at 02:34 PM 0
Share

@chrisvarnsverryvirtualarts True! Could you share your modified code?

avatar image chrisvarnsverryvirtualarts msklywenn · Nov 22, 2017 at 05:04 PM 5
Share

Sure, my solution is to actually load the material and just compare the shader

using UnityEngine; using UnityEditor; using System.Collections.Generic; using System.IO; public class ShaderOccurenceWindow : EditorWindow { [$$anonymous$$enuItem("Tools/Shader Occurence")] public static void Open() { GetWindow<ShaderOccurenceWindow>(); } Shader shader; List<string> materials = new List<string>(); Vector2 scroll; void OnGUI() { Shader prev = shader; shader = EditorGUILayout.ObjectField(shader, typeof(Shader), false) as Shader; if (shader != prev) { string shaderPath = AssetDatabase.GetAssetPath(shader); string[] all$$anonymous$$aterials = AssetDatabase.FindAssets("t:$$anonymous$$aterial"); materials.Clear(); for (int i = 0; i < all$$anonymous$$aterials.Length; i++) { all$$anonymous$$aterials[i] = AssetDatabase.GUIDToAssetPath(all$$anonymous$$aterials[i]); var material = AssetDatabase.LoadAssetAtPath<$$anonymous$$aterial>(all$$anonymous$$aterials[i]); if(material.shader == shader) materials.Add(all$$anonymous$$aterials[i]); } } scroll = GUILayout.BeginScrollView(scroll); { for (int i = 0; i < materials.Count; i++) { GUILayout.BeginHorizontal(); { GUILayout.Label(Path.GetFileNameWithoutExtension(materials[i])); GUILayout.FlexibleSpace(); if (GUILayout.Button("Show")) EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(materials[i], typeof($$anonymous$$aterial))); } GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); } }

apologise for the formatting can't seem to get it to work.

avatar image DMorock chrisvarnsverryvirtualarts · Mar 11 at 12:53 PM 0
Share

Thank you for sharing! Some update with formating, small fixes and ability to change shaders of all found materials feature.

     public class MaterialsUpdate : EditorWindow
     {
         [MenuItem("Tools/Shader Occurence and Update")]
         public static void Open() { GetWindow<MaterialsUpdate>(); }
         Shader shader;
         Shader shaderChangeTo;
         List<string> materials = new List<string>();
         Vector2 scroll;
         void UpdateScrollView()
         {
             // Find materials by shader type selected by user in field "Shader to find"
             string shaderPath = AssetDatabase.GetAssetPath(shader);
             string[] allMaterials = AssetDatabase.FindAssets("t:Material");
             materials.Clear();
             for (int i = 0; i < allMaterials.Length; i++)
             {
                 allMaterials[i] = AssetDatabase.GUIDToAssetPath(allMaterials[i]);
                 var material = AssetDatabase.LoadAssetAtPath<Material>(allMaterials[i]);
                 if (material.shader == shader) materials.Add(allMaterials[i]);
             }
             // Put materials paths to scroll view
             scroll = GUILayout.BeginScrollView(scroll);
             {
                 for (int i = 0; i < materials.Count; i++)
                 {
                     GUILayout.BeginHorizontal();
                     {
                         GUILayout.Label(Path.GetFileNameWithoutExtension(materials[i]));
                         GUILayout.FlexibleSpace();
                         if (GUILayout.Button("Show"))
                             EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(materials[i], typeof(Material)));
                     }
                     GUILayout.EndHorizontal();
                 }
             }
             GUILayout.EndScrollView();
         }
         void OnGUI()
         {
             Shader prev = shader;
             GUILayout.Label("Shader to find");
             shader = EditorGUILayout.ObjectField(shader, typeof(Shader), false) as Shader;
             GUILayout.Label("Shader change to");
             shaderChangeTo = EditorGUILayout.ObjectField(shaderChangeTo, typeof(Shader), false) as Shader;
 
             if (shader != prev)
                 UpdateScrollView();
 
             // Shange material shader to selected by user in field "Shader change to"
             if (GUILayout.Button("Change All"))
             {
                 if (shaderChangeTo && shaderChangeTo != shader)
                 {
                     materials.ForEach(delegate (string material)
                    {
                        Material materialAsset = AssetDatabase.LoadAssetAtPath<Material>(material);
                        materialAsset.shader = shaderChangeTo;
                    });
 
                     UpdateScrollView();
                 }
                 else
                 {
                     Debug.Log("WARNING: MaterialsUpdate - No valid shader change to");
                 }
             }
         }
 }

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Is it worth keeping the built-in render pipeline? 0 Answers

Unity Materials and UV coordinate help 3 Answers

a 'bar' or neon like light. 3 Answers

Best method for implementing alternative view modes? (like Cities: Skylines "Info View") 0 Answers

Materials using textures with black background are not entirely transparent. 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges