Multiplying _Time problem

Hi, noob question, apologies in advance…

I’m trying to make an effect that involves a scroling texture, the speed of which is multiplied by a slider in game (_Speed).

So I did this…

fixed2 scrolledUV = i.uv - fixed2(_Time.y*(_Speed),0);

Which is fine while the texture is scrolling. And when you set the speed variable higher the scroll goes faster. However, while I’m changing the speed variable with the slider, the texture moves aroud in a very jerky manner.

After thinking about it for a while, the reason seemed pretty clear. That, because time is getting bigger and bigger, the “steps” when multiplying with _Speed will also be getting bigger and producing unpredictable results.

I doubt I’m the first person to come across this problem, so is there an easy solution that I’m missing? (I tried just incrementing a variable, but that didn’t do anything (so I’m clearly not understanding something fundamental there too… ))
scrolledUV += fixed2(0.1,0);
Thanks in advance

Don’t use fixed, use a float for UVs. It’s not the problem here, but it’s bad practice. The fixed variable type is defined as a number with a range of at least -2 to 2 and a minimum accuracy of 1/256 across that range. On desktop there isn’t actually support for fixed, so it uses float instead, but some mobile platforms do and this will be bad.

You should be using frac(_Time.y * _Speed) because even when using a float if the number gets too big (ie: the game is running for long enough) you’ll start to see artifacts in the texture that look like it’s being point sampled or the texture is getting lower res. This is caused by floating point precision and the fact the precision gets worse and worse as the number gets bigger. This is also not the problem you’re having, but it’s good to be aware of.

Yep, you got it. When _Time.y is a value of 300 (just 5 minutes) then changing _Speed from 1.0 to just 1.001 is a jump of 0.3 in the UV. Since the UV range is just 0.0 to 1.0 that’s a huge jump.

Your solution of incrementing a variable is the correct one, but you can’t do this in the shader. Those values in the shader are temporary, they exist for one frame only, and only for as long as it takes to calculate each vertex or pixel (depending on if you’re doing the code in the bed or fragment shader). The only real solution for being able to adjust the scroll rate at runtime is to not use a shader to do the panning and instead use a script that updates the material and which increments the offset value. Just remember to wrap the offset here too. In c# it’d be:

scrollUV.x = scrollUV.x % 1f;

1 Like

Thanks Boglus, that’s a fantastic answer, and even answered some other issues I had to questions I hadn’t even asked! Top man!