- Home /
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.
Answer by xibanya · Dec 30, 2019 at 02:15 AM
Try using a RawImage object, when scrolling UVs in a MaskableGraphic (the type used in the UI system) RawImage handles this much more gracefully
Answer by Wappenull · Aug 13, 2020 at 11:07 AM
If it is under Mask, its material will be modified on the way in UI render pipeline to setup for mask rendering.
Thus
Image m_Image; // Target image that we are modifying its material
// Accessing to this material has no effect now if it is under Mask
m_Image.material
// 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;
}
else
{
// 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;
Your answer
![](https://koobas.hobune.stream/wayback/20220612200531im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
UI/Default stencil buffer for only parent? 0 Answers
Custom UI material with Mask ? 2 Answers
UI mask with shader 5 Answers
How to mask on a shader , limit a shader to an area in a ScrollView? 0 Answers