- Home /
Changing material in code doesn't update shader
I am trying to generate a series of Materials, all from on a base texture with varying Albedo detail textures applied to it (decals).
Currently to test this, I have it generating a single material with the very first decal on it and then applying it to an object. The result is that it does this correctly.. but it does not show in game with the new shader unless I manually go in an open the shaders detail panel.
void Update()
{
if(_isAddNew)
{
_isAddNew = false;
// Get the mesh renderer, as this is the renderer type used on _objectToApplyTo.
MeshRenderer newRenderer = _objectToApplyTo.GetComponent<MeshRenderer>();
// Set the material to use a Standard shader.
newRenderer.material = new Material(Shader.Find("Standard"));
// Albedo. Getting the base material, then the main texture from it.
newRenderer.material.mainTexture = _materials[0].GetMaterial().mainTexture;
// Detail Mask
newRenderer.material.SetTexture("_DetailMask",_decals[0]);
// Detail Albedo x2
newRenderer.material.SetTexture("_DetailAlbedoMap",_decals[0]);
_objectToApplyTo.GetComponent<MeshRenderer>().material = newRenderer.material;
}
}
Here is a step by step to help better show this.
I am using Unity 5.0.0f4 Personal Edition.
Thank you for any help and advice.
Sorry for not posting a solution. I just want to confirm that I have the exact same issue with version 5.1.0f3 Personal. I tried assigning a different shader and then switching back but that does not work either. If only we could see what gets executed once we click the material in the editor.
Answer by smcclaire · Jul 07, 2015 at 10:35 PM
It seems the Standard Shader is 'smart' about what parts of the shader are enabled, and you need to use material.EnableKeyword() to tell it to turn on a feature if you're changing things through code. In my case I was assigning a normal map via the "_BumpMap" parameter, which worked after I added the following line to my code:
material.EnableKeyword("_NORMALMAP");
Confirmed Solution, Be sure to use the correct keyword (not the propertyname!), was my mistake first.
see: http://docs.unity3d.com/$$anonymous$$anual/$$anonymous$$aterialsAccessingViaScript.html
Was facing the same issue. This solution works properly in Unity 5.4.3 as well. Thanks a ton!
Answer by saulth · Jul 06, 2017 at 11:52 PM
The comprehensive way to do this is to use the code written by Unity that is executed when you make changes to the material in the Editor. The code is available for download from https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/Inspector/StandardShaderGUI.cs. Then, open up the StandardShaderGUI.cs file and copy out the five functions at the bottom (SetupMaterialWithBlendMode, GetSmoothnessMapChannel, SetMaterialKeywords, MaterialChanged, SetKeyword). Also copy the enums at the top of the class (WorkflowMode, BlendMode, SmoothnessMapChannel) and put in your own class. Then you want to call MaterialChanged() with the WorkflowMode.Metallic on your Material that you modified. Works identically to in-Editor changes :).
Link is broken, you can now find the file here: https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/$$anonymous$$ono/Inspector/StandardShaderGUI.cs
Link is broken again, here's a new one https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/Inspector/StandardShaderGUI.cs
Answer by smcclaire · Jul 08, 2015 at 06:59 AM
Confirmed in 5.1.1f as well. Something doesn't update until you click the inspector.
Your answer
Follow this Question
Related Questions
Color specific sections of a texture 1 Answer
Mobile Shader with Albedo Color and Normal Map 0 Answers
Applying decals / textures to uneven surfaces runtime 1 Answer
Texture2D to Texture3D 2 Answers
Distribute terrain in zones 3 Answers