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. Join us on Dec 8, 2022, between 7 am & 7 pm EST, in the DOTS Dev Blitz Day 2022 - Q&A forum, Discord, and Unity3D Subreddit to learn more about DOTS directly from the Unity Developers.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Unity UI big problem with lacking materialpropertyblock for ui image

Discussion in 'UGUI & TextMesh Pro' started by mahdiii, Nov 30, 2017.

  1. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    104
  2. philipstraw

    philipstraw

    Joined:
    Dec 20, 2013
    Posts:
    3
    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...


     
    MrDizzle26 likes this.
  3. jamespaterson

    jamespaterson

    Joined:
    Jun 19, 2018
    Posts:
    386
    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...
     
  4. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    104
    Image Component
    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.

    Sprite Atlas
    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:

    Code (CSharp):
    1. protected override void OnPopulateMesh(VertexHelper vh)
    (Just make sure respected channels are enabled on the Canvas).

    Quick Hack
    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.
     
    MrDizzle26 and yyysukiii like this.
  5. Shonnyy

    Shonnyy

    Joined:
    Aug 24, 2018
    Posts:
    3
  6. Roy-Hu

    Roy-Hu

    Joined:
    Apr 13, 2021
    Posts:
    7
     
    MrDizzle26 likes this.
  7. Mewel

    Mewel

    Joined:
    Aug 30, 2014
    Posts:
    1
     
    ignatok likes this.
  8. Frog556fb2

    Frog556fb2

    Joined:
    Apr 27, 2019
    Posts:
    13
     
    ignatok likes this.
  9. sdpgames

    sdpgames

    Joined:
    Sep 2, 2014
    Posts:
    16
  10. SolidAlloy

    SolidAlloy

    Joined:
    Oct 21, 2019
    Posts:
    58
  11. SwathingSoap

    SwathingSoap

    Joined:
    Jul 4, 2018
    Posts:
    11
  12. Gerark87

    Gerark87

    Joined:
    Feb 2, 2013
    Posts:
    9
  13. samruilio

    samruilio

    Joined:
    Aug 6, 2015
    Posts:
    6
  14. BrokawayGames

    BrokawayGames

    Joined:
    Feb 12, 2015
    Posts:
    4
  15. temresenpopcore

    temresenpopcore

    Joined:
    Jun 16, 2020
    Posts:
    2
  16. unity_OxfOfvViRhfo-Q

    unity_OxfOfvViRhfo-Q

    Joined:
    Sep 20, 2019
    Posts:
    1
    still waiting for this. please send help.

     
  17. Fressbrett

    Fressbrett

    Joined:
    Apr 11, 2018
    Posts:
    65
  18. LemonCurry

    LemonCurry

    Joined:
    Oct 2, 2014
    Posts:
    1
  19. chakaramba

    chakaramba

    Joined:
    Apr 16, 2019
    Posts:
    6
  20. unity_A1C0D47BAC2E5C4549FC

    unity_A1C0D47BAC2E5C4549FC

    Joined:
    Aug 4, 2021
    Posts:
    1
    I've also run into the same problem. Is there a solution for this yet?
     
  21. smougie

    smougie

    Joined:
    Jan 15, 2020
    Posts:
    12
    Hm... exact problem here.
     
  22. comealong

    comealong

    Joined:
    Mar 20, 2015
    Posts:
    2
  23. Zapan15

    Zapan15

    Joined:
    Apr 11, 2011
    Posts:
    162
  24. neitron

    neitron

    Joined:
    Sep 14, 2014
    Posts:
    13
  25. yeskacher

    yeskacher

    Joined:
    Mar 11, 2021
    Posts:
    1
  26. ignatok

    ignatok

    Joined:
    Feb 3, 2019
    Posts:
    1
  27. Totorole

    Totorole

    Joined:
    Jun 22, 2021
    Posts:
    1
  28. vambier

    vambier

    Joined:
    Oct 1, 2012
    Posts:
    78
    Instead of a propertyblock you can just set the properties individually like this:

    Code (CSharp):
    1. Image image = GetComponent<Image>();
    2.  
    3.         if (image != null)
    4.         {
    5.             image.material.SetFloat("_FloatProperty", floatProperty);
    6.             image.material.SetInt("_IntProperty", intProperty);
    7.         }
    Or am I missing something obvious?
     
  29. treecki

    treecki

    Joined:
    Feb 6, 2017
    Posts:
    28
    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.
     
    Last edited: Jul 25, 2022
  30. BasicallyGames

    BasicallyGames

    Joined:
    Aug 31, 2018
    Posts:
    86


    Just discovered I can't do this. Would be super useful!
     
  31. WafflePanda

    WafflePanda

    Joined:
    Mar 4, 2019
    Posts:
    6
  32. weareinteractive

    weareinteractive

    Joined:
    Apr 14, 2017
    Posts:
    12
  33. Nerdspartan

    Nerdspartan

    Joined:
    Oct 3, 2018
    Posts:
    1
  34. yyylny

    yyylny

    Joined:
    Sep 19, 2015
    Posts:
    84
  35. shelllee

    shelllee

    Joined:
    Apr 12, 2018
    Posts:
    11
  36. Usetheforcemax22

    Usetheforcemax22

    Joined:
    Jul 4, 2022
    Posts:
    1
  37. bugbeeb

    bugbeeb

    Joined:
    Oct 19, 2021
    Posts:
    19
    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:

    Code (CSharp):
    1.     public abstract class BaseImage : Image
    2.     {
    3.         Material clonedMaterial;
    4.  
    5.         public override Material materialForRendering
    6.         {
    7.             get
    8.             {
    9.                 if (clonedMaterial == null)
    10.                 {
    11.                     clonedMaterial = Instantiate(material);
    12.                 }
    13.                 return clonedMaterial;
    14.             }
    15.         }
    16.     }
     
  38. treecki

    treecki

    Joined:
    Feb 6, 2017
    Posts:
    28
    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...
     
  39. Stan88

    Stan88

    Joined:
    May 25, 2017
    Posts:
    1
  40. poomwarning

    poomwarning

    Joined:
    Apr 5, 2020
    Posts:
    1