So, I’m working with some objects in my scene that use dynamic materials which are modified at runtime. However, in an attempt to clean up the code some, things have stopped working. I used to instantiate the materials as needed, modify them and set them. That worked fine, but without proper garbage collection that leads to a reasonable memory leak.
Logically speaking, I should only have to instantiate the material once per object, and modify the instance from there. However, all of my attempts to do this lead to Unity simply ignoring any changes at runtime. I have even debugged the values as they change, and they are changing within the material, there is just no visible change. If I modify the values at start, regardless of order, they work. After start, however, anything I do is ignored unless I instantiate another copy, which should not be the case.
void Start()
{
//This works
Material mat = Instantiate(PosterImage.material);
mat.SetFloat("_EffectAmount", 0f);
PosterImage.material = mat;
//This also works
PosterImage.material = Instantiate(PosterImage.material);
PosterImage.material.SetFloat("_EffectAmount", 0f);
}
Any combination of setting the value and the material in any order within start works perfectly, but if I try to modify that in any way afterwards, it sets the value and does not change anything physically in scene. I would try MaterialPropertyBlocks, but the objects do not have a renderer as they are canvas based. Worst case scenario I will have to go back to instantiating and manually cleaning up the materials, but that is really not something that should be necessary. Is there something I am missing, or is this a limitation of Unity.
Edit: I suppose it helps to mention that the PosterImage variable is an Image, from UnityEngine.UI, so it is governed by a CanvasRenderer as opposed to the standard renderer, as stated above.