Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Masked UI Element's Shader Not Updating

Discussion in 'Unity UI & TextMesh Pro' started by michaelhill, Dec 3, 2015.

  1. michaelhill

    michaelhill

    Joined:
    Nov 4, 2015
    Posts:
    7
    I have a custom shader I am trying to use on a UI Image element. When the element is rendered by itself, the shader works fine. If I make the UI Image a child of an object with a mask, the shader ceases to update unless I disable and reenable it again.

    I have found this problem also happens with the default UI shader as well.

    I am using Unity 5.2.3f1.

    Here is an example of what's happening:

    The top row of images use my custom shader with an animated value.
    The bottom row is using Unity's default UI shader with an animated color element.

    The left column shows unmasked elements.
    The right column shows the same objects placed inside an element with a mask script on it.

    Using "SetMateralDirty()" or "SetAllDirty()" on any of the masking elements on the right does not change the problem.

    Has anyone encountered this problem before? I've tried looking around but haven't found a solution. I've attached a copy of the project shown above to help anyone who might want to have a peek.

    Cheers and thanks for the help -M
     

    Attached Files:

    Last edited: Dec 3, 2015
  2. CMHooe

    CMHooe

    Joined:
    Oct 27, 2014
    Posts:
    2
    In diagnosing a bug in my project today, I've discovered I'm running into this exact same issue. I'm still on 5.2.2f1 on my end, but I was not experiencing the issue prior to that version (the relevant shader and MonoBehavior in question in my case I originally authored in August, so I'm guessing that's 5.1.x timeframe).

    EDIT: just double-checked, and yep everything works fine if I disable the UI mask component outright. Altering the "Show Mask Graphic" field (enabled in my original implementation) does not resolve the issue, however.
     
    Last edited: Dec 5, 2015
  3. michaelhill

    michaelhill

    Joined:
    Nov 4, 2015
    Posts:
    7
    Did you ever make any progress on this? I'm still stuck. Had to work around it by removing the mask, but that shouldn't be the solution.
     
  4. phil-Unity

    phil-Unity

    Unity UI Lead Developer Unity Technologies

    Joined:
    Nov 23, 2012
    Posts:
    1,084
    So guessing here but pretty sure the issue is due to us copying the shader and making modifications to support stencils. My guess is that the material that you are referencing for the animation is not the one that is being used to draw (using the original vs the copied).
     
  5. michaelhill

    michaelhill

    Joined:
    Nov 4, 2015
    Posts:
    7
    So which material would I need to grab in order to do the animation? Would that be the one on the parent with the image mask?
     
  6. michaelhill

    michaelhill

    Joined:
    Nov 4, 2015
    Posts:
    7
    Okay, so it looks like Phil is correct. The reference is being broken in some way that I'm not very clear on. I did some poking around and found the SetGlobalFloat(string propertyName, float value).

    By making the animated value in my shader private, I can then animate it as follows:
    Code (CSharp):
    1. Shader.SetGlobalFloat("_FadeIntensity", lerpValue);
    I only have one object on screen that needs to be animated, so this solution works for me, but it's certainly not a workable solution of you need independent animations for multiple objects on screen.
     
    __blend likes this.
  7. __blend

    __blend

    Joined:
    Apr 8, 2016
    Posts:
    1
    This is really a problem that has to be resolved. Thanks michaelhill for the fast solution.
     
  8. dpolyakov

    dpolyakov

    Joined:
    Dec 18, 2015
    Posts:
    16
    I got the same exact problem (not updating parameters in shader), but I instantiate a material as:

    Code (CSharp):
    1. Image img = GetComponent<Image>();
    2. m_mat = Instantiate(img.material);
    3. img.material = m_mat;
    4.  
    So this solution is not going to work as it will change parameters globally.
    Inside my c# code I call:
    m_mat.SetColor("_Color", m_color);

    Any ideas how to pass parameters to a shader with a stencil?
     
  9. nxtboyIII

    nxtboyIII

    Joined:
    Jun 4, 2015
    Posts:
    218
    I'm experiencing the same issue...
     
  10. nxtboyIII

    nxtboyIII

    Joined:
    Jun 4, 2015
    Posts:
    218
    It looks like a work around is by disabling the image, then re-enabling it right after
     
  11. cschmidtHT

    cschmidtHT

    Joined:
    Aug 31, 2016
    Posts:
    3
    Phil-Unity had it right but didn't elaborate enough to keep you from just hacking around with the global parameters.

    The Mask object causes a modified material to be rendered rather than the baseMaterial so it is no longer rendering the texture that you are updating with the "material" property. Using set on the materialForRendering property will set the correct material if a mask is involved.

    So in your project adding

    topImageMasked.materialForRendering.SetFloat("_FadeIntensity", lerpValue);
    bottomImageMasked.materialForRendering.color = newColor;
     
  12. sandbok

    sandbok

    Joined:
    Dec 1, 2016
    Posts:
    7
    Thank you so much! This had been giving me a lot of trouble, but using "materialForRendering" fixes my problem.
     
  13. Piflik

    Piflik

    Joined:
    Sep 11, 2011
    Posts:
    214
    I have encountered the problem now as well. But .materialForRendering does not work in my case, since I need to change the properties while the mask is disabled and enable the mask later. Use .material or .materialForRendering does not make a difference, since .materialForRendering points to two different materials, the original and the stenciled copy, depending on the state the mask is in, and the copy is not updated when the original is edited.

    I filed a bug-report (case 994413) in the hopes that this behaviour might be fixed in a future release.
     
    Last edited: Jan 29, 2018
  14. 334499p

    334499p

    Joined:
    Nov 2, 2014
    Posts:
    1
    Incase anyone's looking for a solution- After setting the material's property, simply disable and enable the graphic component in two lines : img.enabled = false; and then img.enabled = true;