Why can't I alter a Texture offset on a material, if its used in a Mask or Scroll rect?

using unity 5.6.3p3
We have several prefab inserts that are placed into a scrolling layout. (imagine a leaderboard)
I have a shader (that works with unity masks) to scroll a layer on one of those items to make a sheen/shining effect. It scrolls the texture’s uv offset on a material.
The material is on a “Image” its the background for the Ui object.
This works great everywhere in the game except if you put it inside a hierarchy with a mask (scroll layout also needs a mask )
I even tried passing a custom scroll value to the shader… but unity somehow also resets this.

If my object is outside the mask it works fine. If its inside the mask, its as if my uv’s are all locked to 0,0,width,height.

If I hard-code a u,v offset in the shader… it renders with those offsets ok. So unity is blocking those values being sent to the shader somwehow. How does it do this ? and why ?
Or is there some extra code I need to add to support masks with texture offsets ?
Is there any way to get around this issue ?

Thanks in advance for any insight/help into this issue.

Did you find a solution? I need to know aswell…

Try using a RawImage object, when scrolling UVs in a MaskableGraphic (the type used in the UI system) RawImage handles this much more gracefully

If it is under Mask, its material will be modified on the way in UI render pipeline to setup for mask rendering.


Image m_Image; // Target image that we are modifying its material

// Accessing to this material has no effect now if it is under Mask

// Instead access to generated "output" material
Material m = m_Image.materialForRendering;
Vector2 offset = m.mainTextureOffset;
offset.x += 0.1f;
m.mainTextureOffset = offset;

(Advanced usage) For a quick and dirty check, you can also check if that image component is under such magical material pipeline. Compare its original material with materialForRendering and pick correct material to modify.

/* Script head ////////////////////*/
Image m_Image;
Material m_Instanced;

/* In update function ////////////////////*/

Material modifying;
if( m_Image.materialForRendering != m_Image.material )
    // It is under mask or something that modify material instance
    modifying = m_Image.materialForRendering;
    // Access to original material instead
    // But if we use m_Image.material directly, this will modify to original "Asset" version of material
    // Which is bad if you share it with several images, and it will trigger asset dirty every play.
    // To really make a copy of it. new Material first
    if( m_Instanced == null )
        m_Instanced = new Material( m_Image.material );
        m_Instanced.name = m_Instanced.name + "cloned"; // Alter it name a bit so we know
        m_Image.material = m_Instanced; // Change Image to use this new copy
    modifying = m_Instanced; // We will modify the copy instead of real asset one

// Proceed to modify as usual
Vector2 offset = modifying.mainTextureOffset;
offset.x += 0.1f;
modifying .mainTextureOffset = offset;