Get/Set 来自 Unity 着色器图形的时间值

Get/Set Time value from Unity shader Graph

我用以下节点创建了脉动闪亮效果:

Abs(Time * speed) => sine

我有一个介于 0 和 1 之间的振荡值,但问题是该值可能从 0 到 1 之间的任何值开始,具体取决于时间值。

我正在尝试找出一种方法,可以在着色器外部获取该值,以便脚本可以将 属性 设置为偏移量:

float offset = GetTimeFromShader();
material.SetFloat("_Offset", offset);

着色器以:

结束
Abs((Time - offset) * speed) => sine

这将确保脉动从 0 开始。

另一种可能性是在着色器模拟中创建一个递增的 vector1:

temp += Time.deltaTime * speed;

但是 Shader graph 阻止了节点循环。

我可以在脚本中完成并将其传递给着色器 属性 但如果有办法将其全部保留在着色器中。

我认为问题在于您无法保证着色器开始渲染时 Time 的值是多少。这也意味着提供偏移量是没有实际意义的,因为您不知道偏移量需要的值(并且它可能每次都会更改)。要执行您要求的操作,需要使用脚本 MaterialPropertyBlock.

设置的着色器 属性

I have an oscillating value between 0 and 1 but the problem is that the value may start from anything between 0 and 1 depending on the Time value.

这就是你的问题所在。你可以很容易地改变你的着色器,而不是让振荡从 0 开始并且独立于内置着色器时间,不是吗?这将意味着从您不想要的脚本驱动着色器,但我认为在这种情况下这不是坏习惯,因为听起来您希望振荡直接与游戏中的特定事件相关联- 所以非常努力地将着色器代码与应用程序代码分离在这里有点多余 - 它们需要以某种方式链接到某个地方。

要将着色器与内置着色器时间分离,而不是 Abs(Time * speed) 将时间替换为您控制的 属性,即 Abs(phase * speed).

我使用以下代码来播放冲击波效果,并始终确保它从我想要的位置开始:

// ensures shockwave plays once and does a full wave over duration
IEnumerator PlayShockwave(float duration, Renderer shockwave)
{
    float timeElapsed = 0f;
    float speed = Mathf.Abs(shockwave.material.GetFloat("_Speed"));
    float phase = shockwave.material.GetFloat("_Phase");
    float targetPhase = 1 / speed;

    while (timeElapsed <= duration)
    {
        timeElapsed += Time.deltaTime;
        shockwave.material.SetFloat("_Phase", Mathf.Lerp(phase, targetPhase, timeElapsed / duration));
        yield return new WaitForEndOfFrame();
    }
}

并用 StartCoroutine(PlayShockwave(2.0f, YourRenderer));

调用它