Shader中表示时间
在 Unity Shader 中,时间通常用于实现动画、周期性变化或随时间演进的效果。Unity 提供了几种内置方式来表示时间,
1. 内置时间变量
Unity 在 UnityCG.cginc
中定义了几个全局时间变量:
_Time
四维向量,包含不同时间尺度:
float4 _Time; // (t/20, t, t*2, t*3)
// t = 自游戏开始的时间(秒)
_Time.x
:t/20
(缓慢变化)_Time.y
:t
(常用,直接表示时间)_Time.z
:t*2
(两倍速)_Time.w
:t*3
(三倍速)
应用场景:基础动画、周期性变化。
_SinTime
和 _CosTime
预计算的正弦和余弦时间值:
float4 _SinTime; // (sin(t/8), sin(t/4), sin(t/2), sin(t))
float4 _CosTime; // (cos(t/8), cos(t/4), cos(t/2), cos(t))
应用场景:无需手动计算三角函数的平滑动画。
2. 使用示例
2.1 纹理滚动(流动效果)
fixed4 frag (v2f i) : SV_Target {
// 随时间水平滚动纹理
float2 scrolledUV = i.uv + float2(_Time.y * 0.5, 0);
fixed4 col = tex2D(_MainTex, scrolledUV);
return col;
}
2.2 颜色脉动效果
fixed4 frag (v2f i) : SV_Target {
// 使用 _SinTime.w 实现颜色周期性变化(范围:-1 到 1)
float pulse = (_SinTime.w + 1) * 0.5; // 转换为 0 到 1
fixed4 baseCol = tex2D(_MainTex, i.uv);
return baseCol * pulse; // 颜色强度随时间脉动
}
2.3 波纹效果
fixed4 frag (v2f i) : SV_Target {
// 计算到中心的距离
float2 center = float2(0.5, 0.5);
float dist = distance(i.uv, center);
// 随时间变化的波纹
float wave = sin(dist * 20 - _Time.y * 5);
wave = saturate(wave * 0.5 + 0.5); // 转换为 0 到 1
fixed4 col = tex2D(_MainTex, i.uv);
return col * wave; // 应用波纹效果
}
3. 自定义时间变量
若需要更精确的控制(如独立于游戏时间的效果),可通过 C# 脚本向 Shader 传递时间值:
3.1 Shader 代码
// 在 Shader 中声明属性
uniform float _CustomTime;
fixed4 frag (v2f i) : SV_Target {
float animProgress = frac(_CustomTime); // 0~1 循环
// 使用 animProgress 控制动画...
}
3.2 C# 脚本
using UnityEngine;
public class TimeController : MonoBehaviour {
public Material targetMaterial;
private float customTime = 0f;
void Update() {
customTime += Time.deltaTime;
targetMaterial.SetFloat("_CustomTime", customTime);
}
}
4. 注意事项
-
时间精度:
_Time
基于游戏时间,受暂停、减速等影响。- 若需要不受游戏控制的时间,可使用
Time.realtimeSinceStartup
通过脚本传递。
-
性能优化:
- 避免在片元着色器中频繁计算三角函数,优先使用
_SinTime
和_CosTime
。
- 避免在片元着色器中频繁计算三角函数,优先使用
-
多 Pass 一致性:
- 在多 Pass Shader 中,不同 Pass 的时间可能略有差异,如需一致性可手动缓存时间值。
总结
方法 | 优点 | 适用场景 |
---|---|---|
_Time.y |
简单易用,内置支持 | 基础动画、周期性变化 |
_SinTime |
预计算三角函数,性能优 | 平滑波动效果 |
脚本传递时间 | 精确控制,独立于游戏时间 | 特殊效果(如 UI 动画) |
通过合理使用时间变量,你可以实现纹理动画、颜色变化、物理模拟等多种动态效果。