Search Unity

[SOLVED] How to change material properties at runtime?

Discussion in 'Scripting' started by Tomas_Kok, Jul 14, 2015.

  1. Tomas_Kok

    Tomas_Kok

    Joined:
    Oct 5, 2014
    Posts:
    12
    Hi,

    How can I change material properties at runtime? I am trying to make my chacacter transparent when my camera gets close. I am using the standard shader for every material.

    Code (CSharp):
    1. private Material[] materials;
    2.  
    3. void Start(){
    4.             materials = player.GetComponent<Renderer>().materials;
    5.         }
    6.  
    7. void XRay(){
    8.             foreach (Material mat in materials) {
    9.                 mat.SetFloat ("_Mode", 3); //This sets the Standard Shaders Rendering mode to transparent
    10.                 mat.SetColor ("_Color", new Color(mat.color.r, mat.color.g, mat.color.b, 0.25f));
    11.             }
    12.         }
    function XRay gets called at the right moment, and I can see the right changes in the inspector: the rendering mode of all materials becomes transparant and the alpha of the Albedo property changes, without changing the color.
    The problem is, it only changes in the inspector and not in my scene. If I than change the alpha property manually while running the game, the material in the scene suddenly updates. So somehow the material does not update at runtime. Probably the rendering mode, because only changing the color this way works.
    I think it has something to do with shadervariantcollections, but I don't understand what the documentations says about them and exactly how they work.
    And why isn't here just a function that tell unity to update the material/shader?

    Thanks in advance.
     
  2. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    974
    are you expecting to change all objects using said material? if so, you need to use the Renderer.sharedMaterial. Keep note that, as far as I know, any changes to the shared material will be kept even after you stop the game.

    If you want to get around that, look at the answer here
    http://answers.unity3d.com/questions/396347/how-to-stop-renderersharedmaterialsetcolor-writing.html
    It basically says that you assign your sharedmaterial to a copy of itself at runtime so now any edits made will be on the copy that will be removed when the game ends.

    If your problem isnt what I stated above, then I am not sure as I do not know materials that much.
     
  3. Tomas_Kok

    Tomas_Kok

    Joined:
    Oct 5, 2014
    Posts:
    12
    Thank's for your reply, but that's not what I'm looking for, and it doesn't work either. I'll explain in more detail (and a little update). I hope that my english is understandable:

    I want to make my player character transparent, so I need to change all the materials applied to him to rendering mode 'transparant', and set the alpha value of the color to something lower than 1 (in this case 0.25). My script does exactly that. I can see the change in the inspector while the game is running, but in the scene it does not change at all, unless I make a little change in the inspector manually (changing the alpha value just a little for example), than it updates everything in the scene the way I want it.

    'sharedMaterial' adresses only one material on my mesh, while I need to get them all. 'materials' makes a copy of all materials on my mesh (or technically, on the renderer) and stores them into an array. This way I can adress all of them in a foreach loop, and I only change those on my mesh (because it is a copy).

    Furthermore, 'sharedMaterial' has the same problem. When I get the sharedMaterial of a mesh and change the rendering mode to transparant and the alpha value to 0.25, nothing happens in the scene view (only in the editor).

    I guess that the problem is, that I change the rendering mode of the material, and unity needs to know that when loading te scene. I heard that there is a way of preloading shadervariants (stored in shadervariantcollections) and a function ShaderVariantCollection.Warmup(); but I do not understand how it works or how I have to set them up.

    Something that I did try is making an empty gameObject, giving it a renderer component and applying copies of the materials of my player character in transparant mode. This way I wanted Unity to preload those materials in transparant mode also, but it didn't change anything.

     
  4. Julien_

    Julien_

    Joined:
    Nov 12, 2013
    Posts:
    43
    There are a few more parameters you need to set in order to change the material to transparent. Someone gave a solution for this in this thread: http://forum.unity3d.com/threads/ac...ard-shader-via-scripting.287002/#post-1961025

    Please also read the posts below the one I linked, because this doesn't work in a finished build. Unity is stripping out all shader variants that are not used at design time.

    The solution given in the other thread suggest to create a "dummy" material with the given settings and assign it to an empty GameObject so the Shader does get included in the build. When I tried to do something similar, I think I ended up creating a transparent material in the Editor and just switched between materials instead of modifying it.
     
    indieDoroid and Tomas_Kok like this.
  5. Tomas_Kok

    Tomas_Kok

    Joined:
    Oct 5, 2014
    Posts:
    12
    Thank's, that works like a charm! Setting up the other parameters made it work in the editor and scene view, but not in the build. Making an empty gameObject with the materials setup how you want them to become (like I tried to do in the first place, when I did not know about the other parameters), made it work in the build also.
     
    indieDoroid and RodrigoSeVeN like this.