Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question Importing and immediately assigning shader to material.

Discussion in 'Scripting' started by lmaoroot2, Oct 17, 2021.

  1. lmaoroot2

    lmaoroot2

    Joined:
    May 6, 2021
    Posts:
    17
    I'm trying to basically store all of the materials paths that use a specific shader, in this case: test/oldshader, into a list of string type. Then we remove test/oldshader and import a new shader called test/newshader... I then want to apply the Material that was using test/oldshader, which is now an Hidden/InternalErrorShader, but i dont want to check for InternalErrorShader because there might be other InternalErrorShaders in the project that it hasnothing to do with. This method is supposed to just change the oldshaders to the newshaders, not touching anything else really. :).
    Anyways, the problem I think im having is that the UnityEditor is not updating and therefore thinks that it doesn't have a "test/newshader" so it either sets an Hidden/InternalErrorShader as the shader for the material or just doesnt do anything. How can I fix this issue. I want to just apply it after importing of the asset of test/newshader. I have my entire method below with placeholders to cut out "unimportant" details.

    Any help is appreciated.
    Thanks.

    Code (CSharp):
    1. string[] guids = AssetDatabase.FindAssets("t: material");
    2. List<string> mats2Fix = new List<string>();
    3. foreach (string guid in guids)
    4. {
    5.     string p = AssetDatabase.GUIDToAssetPath(guid);
    6.     Material temp = (Material)AssetDatabase.LoadAssetAtPath(p, typeof(Material));
    7.     if (temp != null && temp.shader.name.ToLower().Contains("test/oldshader")) mats2Fix.Add(AssetDatabase.GetAssetPath(temp.GetInstanceID()));
    8. }
    9.  
    10. // Place Holder for Removing test/oldshader
    11.  
    12. // Place Holder for Importing test/newshader.unitypackage with test/newshader, which is the new shader I want to apply to the materials that were using test/oldshader
    13.  
    14. foreach (string mat2Fix in mats2Fix)
    15. {
    16.     if (File.Exists(Application.dataPath + mat2Fix.Substring(6))) // Substring because Application.dataPath already contains "Assets", which is also in mat2Fix... so substring it but we need it later for loading.
    17.     {
    18.     Material temp = (Material)AssetDatabase.LoadAssetAtPath(mat2Fix, typeof(Material));
    19.     temp.shader = Shader.Find("test/newshader");
    20.     }
    21. }
    22. AssetDatabase.SaveAssets();
     
    Last edited: Oct 17, 2021
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    Hm, see if it has any OTHER random shader that you know you can find.

    This will isolate if you are a) not searching for the shader properly, or b) the newshader really is the only one not present.
     
  3. lmaoroot2

    lmaoroot2

    Joined:
    May 6, 2021
    Posts:
    17
    I just now attempted to change the materials shader to just the regular old Standard shader, which worked flawlessly. So I believe that my idea of why it's not setting it to test/newshader is correct, its that the unityeditor is not finding it since the importing takes place shortly before and doesn't have enough time to actually update the frame or something. I'd also like to point out that using the same method, with just the changing of shader part of the script, it flawlessly changes it to test/newshader without any problems. This only occurs when I import the package and shader through the script THEN attempt to apply the shader to the material. So, that's why I think that it's the UnityEditor just not being refreshed... However, I'm not sure where to go from here. I'm completely lost as to what I can do now about this... If you or anyone can guide me in the right direction, I would be much appreciated.
     
  4. lmaoroot2

    lmaoroot2

    Joined:
    May 6, 2021
    Posts:
    17
    Help would be much appreciated, im currently stuck.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    It sounds like this is probably the issue: I've had issues with this name search before, but it was years ago. I just put Shader.Find() into the same camp of "functions that the compiler cannot help you with" and avoid it.

    I know this is only an editor script, but this method also has runtime issues because unless that shader is referenced by at least one material in your built game, it will silently get asset-stripped and fail to be found. Unity does NOT include all shaders, only what is apparently used.
     
  6. lmaoroot2

    lmaoroot2

    Joined:
    May 6, 2021
    Posts:
    17
    Are there any alternatives? Maybe finding the asset for the shader itself and applying it manually? but then again, I don't know how I would achieve this.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    I've only used runtime replacements, and for that I just make a material and get it that way, like any other asset.

    Not sure how that maps to whatever editor tool you're making.