Search Issue Tracker
Won't Fix
Votes
2
Found in
2022.3.55f1
6000.0.34f1
6000.1.0b2
6000.2.0a1
Issue ID
UUM-92586
Regression
No
Global shader variables _Time and _TimeParameters do not reset when a Scene is loaded in URP
Reproduction steps:
1. Open the attached “BugShaderTime.zip” project
2. Open the “Assets/Scenes/SampleScene.unity“ Scene
3. Enter the Play Mode
4. Observe than _Time.y, _TimeParameters.x and Time.timeSinceLevelLoad have identical values
5. Press the "Reload Scene" button in the Game view
6. Observe the Game view
Expected result: _Time.y, _TimeParameters.x and Time.timeSinceLevelLoad have identical values
Actual result: _Time.y, _TimeParameters.x and Time.timeSinceLevelLoad do not have identical values
Reproducible with: 2022.3.55f1, 6000.0.34f1, 6000.1.0b2
Reproducible on: Windows 11
Not reproducible on: No other environment tested
Notes:
* Reproducible in the Player
* Not reproducible when using built-in RP
* Link to discussions: [https://discussions.unity.com/t/in-92796-global-shader-variables-time-and-timeparameters-appear-to-be-wrong/1582822/2|https://discussions.unity.com/t/in-92796-global-shader-variables-time-and-timeparameters-appear-to-be-wrong/1582822/2|smart-link]
Comments (1)
-
Peter77
Apr 25, 2025 04:54
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Foldout arrow indent is misaligned in the Inspector when used in Custom Type
- [Android] The Player screen turns black when playing a video under certain conditions
- Search window icons at the bottom are cut off when Search window is resized vertically
- "Try something else?" text label is cut off when searching for a long text in the Search window
- Rendering Debugger window sections do not have a minimum width set when resizing with the slider in the middle of the window
Resolution Note:
Hello.
It is correct that _Time is not Time.timeSinceLevelLoad but instead Time.time in URP/HDRP and that the documentation does not reflect this. We will update the documentation, but unfortunately we cannot change the behavior at this point, because it would be a breaking change for users that rely on the current behavior.
However I can provide you with this ScriptableRendererFeature that use can use in your project to override the variables, so it behaves like it does in the built in render pipeline:
```
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
public class ShaderTimeOverride : ScriptableRendererFeature
{
ShaderTimeOverridePass m_ScriptablePass;
public override void Create()
{
m_ScriptablePass = new ShaderTimeOverridePass
{
renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses
};
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(m_ScriptablePass);
}
class ShaderTimeOverridePass : ScriptableRenderPass
{
// Shader properties:
static readonly int timeNameID = Shader.PropertyToID("_Time");
static readonly int sinTimeNameID = Shader.PropertyToID("_SinTime");
static readonly int cosTimeNameID = Shader.PropertyToID("_CosTime");
static readonly int deltaTimeNameID = Shader.PropertyToID("unity_DeltaTime");
static readonly int timeParametersNameID = Shader.PropertyToID("_TimeParameters");
static readonly int lastTimeParametersNameID = Shader.PropertyToID("_LastTimeParameters");
float savedTimeLastFrame;
private class PassData
{
public Vector4 timeVector;
public Vector4 sinTimeVector;
public Vector4 cosTimeVector;
public Vector4 deltaTimeVector;
public Vector4 timeParametersVector;
public Vector4 lastTimeParametersVector;
}
static void Execute(PassData data, UnsafeGraphContext rgContext)
{
UnsafeCommandBuffer cmd = rgContext.cmd;
cmd.SetGlobalVector(timeNameID, data.timeVector);
cmd.SetGlobalVector(sinTimeNameID, data.sinTimeVector);
cmd.SetGlobalVector(cosTimeNameID, data.cosTimeVector);
cmd.SetGlobalVector(deltaTimeNameID, data.deltaTimeVector);
cmd.SetGlobalVector(timeParametersNameID, data.timeParametersVector);
cmd.SetGlobalVector(lastTimeParametersNameID, data.lastTimeParametersVector);
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
const string passName = "Override Shader Time";
using (var builder = renderGraph.AddUnsafePass<PassData>(passName, out var passData))
{
builder.AllowPassCulling(false);
float time = Time.timeSinceLevelLoad; // <-- Uses Time.timeSinceLevelLoad instead of Time.time!
float deltaTime = Time.deltaTime;
float smoothDeltaTime = Time.smoothDeltaTime;
float timeLastFrame = savedTimeLastFrame;
float timeEights = time / 8f;
float timeFourth = time / 4f;
float timeHalf = time / 2f;
float sinTime = math.sin(time);
float cosTime = math.cos(time);
passData.timeVector = time * new Vector4(1f / 20f, 1f, 2f, 3f);
passData.sinTimeVector = new Vector4(math.sin(timeEights), math.sin(timeFourth), math.sin(timeHalf), sinTime);
passData.cosTimeVector = new Vector4(math.cos(timeEights), math.cos(timeFourth), math.cos(timeHalf), cosTime);
passData.deltaTimeVector = new Vector4(deltaTime, 1f / deltaTime, smoothDeltaTime, 1f / smoothDeltaTime);
passData.timeParametersVector = new Vector4(time, sinTime, cosTime, 0.0f);
passData.lastTimeParametersVector = new Vector4(timeLastFrame, math.sin(timeLastFrame), math.cos(timeLastFrame), 0.0f);
savedTimeLastFrame = time;
builder.SetRenderFunc((PassData data, UnsafeGraphContext rgContext) => Execute(data, rgContext));
}
}
}
}
```