从Unity着色器图形获取/设置时间值

问题描述

我创建了一个带有以下节点的脉动闪亮效果:

Abs(Time * speed) => sine

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

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

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

并且着色器最终以:

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

这将确保脉动从0开始。

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

temp += Time.deltaTime * speed;

但是Shader图可以防止节点循环。

我可以在脚本中完成此操作并将其传递给着色器属性,但是如果有一种方法可以将其全部保留在着色器中。

解决方法

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

,

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

这就是你的问题。你可以很容易地改变你的着色器,而不是让振荡从 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));

调用它

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...