It’s time to make things move!

Scrolling UV’s can be useful in a lot of scenarios, especially with visual effects for waterfalls, scan lines on tvs etc (Pretty much anything that moves)!

For the last #NotGDC jam, I used a slightly similar effect in my submission FOMO, to scroll a shine across the models UV’s, signalling to the player that the item can be interacted with. Shader development can be an important aspect of UX and game design.

In our material properties, we can allow inputs for the X and Y speed of the UV scrolling individually. Ideally in the inspector, we would prefer a float2, but as far as I can tell, it’s not possible, the only vector input allowed is a float4. So we will have to make do with separate properties.

Shader "Ryans/ScrollingUV"
        _MainTex("Diffuse", 2D) = "white" {}
        _ScrollSpeedX("Scroll Speed X", Float) = 0
        _ScrollSpeedY("Scroll Speed Y", Float) = 0

Later, we need to make sure we define all of these variables before the vertex shader, just like usual with anything we add inside Properties{}.

            sampler _MainTex;
            float4 _MainTex_ST;
            // We can define two variables on the same line with a comma
            float _ScrollSpeedX, _ScrollSpeedY;

Since the #include "UnityCG.cginc" library allows us to use _Time.y (time at normal speed), we can use this multiplied by our user-defined X and Y Scroll Speeds to get a value we can add to our uv0 channel which updates with time.

            fixed4 frag (vertexOutput o) : SV_Target
                half UVOffsetX = _ScrollSpeedX * _Time.y;
                half UVOffsetY = _ScrollSpeedY * _Time.y;
                half2 uv = o.uv0;
                // You can alter a single channel of a variable with .x .y etc
                uv.x += UVOffsetX;
                uv.y += UVOffsetY;

                float4 colour = tex2D(_MainTex, uv);
                return colour;

I used halfs in this, as I couldn’t notice a difference between a float offset and a half offset. I figured this might be better for performance but I haven’t profiled it!