A Unity ID allows you to buy and/or subscribe to Unity products and services, shop in the Asset Store and participate
in the Unity community.
Separate names with a comma.
Discussion in 'UGUI & TextMesh Pro' started by mahdiii, Nov 30, 2017.
Hello. I'm creating a UI where the user can select from over a list of over a hundred images being draw with a custom shader. At the moment I have to create new materials for each image. This is a mobile game so resources are tight. Any suggestions for how to work around this other than...
Have you considered maybe packing into an atlas and offsetting the UV coords? Or maybe a texturearray if your target hardware level supports this? Obviously, MPB would be better...
If the images are Sprites (Atlased or not), you can use the same Material with the Image component and change only the sprite which is configured as PerRendererParameter in the shader.
Just like the poster above mentioned, Atlas is one way to improve performance.
I'm not sure if there is a way to create SpriteAtlas at runtime. There should be I think.
If images aren't in the same texture, they will not be batched anyway, so the same or different material doesn't really make a difference.
Custom UI Graphic
If each image's material needs to be configured differently (as this is what this whole topic is all about) there is a proper way of passing the data through vertices with the Graphic Component's:
protected override void OnPopulateMesh(VertexHelper vh)
(Just make sure respected channels are enabled on the Canvas).
Also, as a quick hack, I sometimes write UI shaders that use vertex.colour's RGBA channels as some other parameters:
Red would be Thickness of lines, Green - Amount of Contrast, Red - Maybe Shaky effect or something Just to give an example. Obviously, this doesn't work if you actually need to control the colour.
still waiting for this. please send help.
I've also run into the same problem. Is there a solution for this yet?
Hm... exact problem here.
Instead of a propertyblock you can just set the properties individually like this:
Image image = GetComponent<Image>();
if (image != null)
Or am I missing something obvious?
Yes @vambier you're correct that you can set the individual float and int, but it's on 1 material. So if two buttons have that material, both would be changed. With a material property block, you can change the float and int on one button but it won't affect the other. It's like creating a new material without having to instance a new material directly.
Just discovered I can't do this. Would be super useful!
I'm using URP and have read that cloning a material is better than using material property blocks because the render pipeline will batch draw calls "To achieve this, use as few shader variants as possible. You can still use as many different materials with the same shader as you want." (https://docs.unity3d.com/Manual/SRPBatcher.html#how-the-srp-batcher-works). The graphic class has a property called `materialForRendering` that you can override which is what actually gets sent to the renderer. So instead of calling `material.SetFloat()` I inherit from my base class and use `materialForRendering.SetFloat()` and override that prop with a cloned material. Here is the base class:
public abstract class BaseImage : Image
public override Material materialForRendering
if (clonedMaterial == null)
clonedMaterial = Instantiate(material);
I may be wrong in this, but from what you quoted, it seems to be saying to use as few "duplicate" shader variants as possible. I don't believe a MaterialPropertyBlock is a duplicate of a shader. In fact, the article you linked actually mentions that you may want to break SRP Batcher because using GPU instancing is more efficient.
"In some rare cases, you might want to intentionally make particular GameObjects incompatible with the SRP Batcher. For example, if you want to use GPU instancing, which isn’t compatible with the SRP Batcher. If you want to render many identical meshes with the exact same material, GPU instancing can be more efficient than the SRP Batcher. "
I'd also reference this article for understanding why MaterialPropertyBlocks can be much more efficient than instantiating multiple different materials.
On a different note, I'm surprised there haven't been any updates from Unity on the MaterialPropertyBlocks for UI. I've been following this thread for a while...
+1, yes please: UI Canvas 'MaterialPropertyBlocks'
Probably ain't matter since it's almost been 3 years now but, +1.