Shader time since object instantiation instead of time since level load?

Hi all,

I am trying to make a main menu with some gameobjects in the background which persist between scenes by means of the DontDestroyOnLoad function.
Unfortunately one game object is using a custom shader which is scrolling an uv map based on the shader variable ‘_Time’ (Time since level load). See relevant lines of code below:

float2 uv = input.tex.xy;
uv.x += _Time * _CloudSpeed;

This game object is the ‘Planet Shader and Shadowing System, by Muntadas Quentin’, from the Unity asset store. Link to unity asset store


The problem i am having is that the uv map of the cloud texture is reset every time i load an new scene, causing the texture to jump back to its starting position.
What i have tried so far to solve this problem:

  1. First I tried to copy the ‘_Time’ value to another ‘_TimeOffset’ variable via C# script just before loading a new scene and then add this ‘_TimeOffset’ to the ‘_Time’ variable when calculating the uv map positions for the new scene. Although this solves the problem of the texture jumping back to its starting position when loading a new scene it causes a new problem where the texture now jumps briefly backwards (flickers) for 1 or 2 frames before jumping to the correct scroll position.Link to YouTube

    float2 uv = input.tex.xy;
    uv.x += (_Time +_TimeOffset) * _CloudSpeed;
    
  2. Secondly I tried to use the shader variable ‘unity_DeltaTime’ to avoid the use of the shader variable ’ ‘_Time’. This resulted in the cloud texture not scrolling at all.

"

 float2 uv = input.tex.xy;
_TotalTime += unity_DeltaTime;
uv.x += _CloudSpeed * _TotalTime;

If someone can tell me how to modify this shader so it doesn’t reset the uv map when switching scenes it would be greatly appreciated.

Best regards,
Kaz

Hi all,

I found a work around in using the Texture Offset variables of the texture data (_ST suffix) and modifying it with C# script.
On one hand its feels straight forward but on the other hand i don’t like the shader being dependent on c# script.

Below is the C# script

[Range(-0.01f, 0.01f)] [SerializeField] private float cloudSpeed = 0f;
....
    void Update()
    {
        float offset = Time.time * cloudSpeed;
        PlanetMaterial.SetTextureOffset("_CloudMap", new Vector2(offset, 0));
    }

Below is the modified changed shader code.

uniform float4 _CloudMap_ST;
......
float2 uv = input.tex.xy;
uv = uv + _CloudMap_ST.zw;

BR, Kaz

You could also update the shader to use a Vector1 property to drive the change instead of being reliant on the built in shader _Time.

That way you can persist the current state (i.e the time) through scene loads since you are already using DontDestroyOnLoad. See this answer for further clarification on how to make the shader independent of the built in shader time: http://answers.unity.com/answers/1801454/view.html