【问题标题】:Changing a shader blend on pointer click over time随着时间的推移更改指针单击时的着色器混合
【发布时间】:2018-02-03 15:38:08
【问题描述】:

我在 Unity 中有一个着色器,它设置为在两个纹理之间混合。这已设置好并且工作正常。

Blend 的范围为 0-1,在离线模式下效果很好。

    _Blend1("Blend between _MainTex and Texture2", Range(0, 1)) = 0

我已经设置了一个可以正常工作的 OnClick 指针。它本质上将一个值切换为 true 并在更新中激活它。我在 0(第一个纹理和 1(第二个纹理)之间切换值方面取得了一些成功。

    public void OnColorChangeClick()
{
    if (newSwitchOne)
    {
        switchOn = true;         
    }
    else if (newSwitchTwo)
    {
        switchOff = true; 
    }
}

在 switchOn 为真时的更新中,我有一个 while 循环运行并增加混合的计数。

 void Update()
{
    rend.material.SetFloat("_Blend1", up);
    while (switchOn == true) {
        for (int i = 0; i < 10; i++)
        {
           //StartCoroutine(Wait());
            up = Time.deltaTime * (up + 0.1f);
        }
        switchOn = false;
        print(switchOn);
    }
}

我遇到的问题是值增量不能与 time.deltaTime 一起工作。我看到 Time.deltatime 可能无法在 while 循环中工作。所以我也尝试了一个带有 WaitForSeconds 的 CoRoutine。这些都没有给我我想要的增量。

我已经研究过这个 Lerping - 但我不知道如何 Lerp 这样的值 - 我一直在寻找,也许是在错误的地方。

有人能指出正确的方向吗?

【问题讨论】:

  • 不敢相信在所有这些答案中都没有提到这一点。您的代码中的问题是因为您在 Update 函数中使用了 Time.deltaTime,这是一个 void 函数。 Time.deltaTime 不会在 Update 函数中改变。将所有这些代码移动到协程(IEnumerator)函数中,然后将yield return null 添加到while 循环的末尾,您的问题应该得到解决。
  • 感谢程序员的评论。是的,我需要阅读 time.deltatime 多一点。我一直认为这是理所当然的。
  • 没问题。您还需要学习协程,因为当涉及到doing something over time 时您需要它们,否则您将在 Update 函数中执行它,该函数将永远运行而不是“运行然后结束”。编码愉快!
  • 我对带有 waitforseconds 的 corotuine 很熟悉 - 问题是它不是在打球,而我没有看到问题!发生了冲突。我会到达那里。但是还是谢谢你们-回复有帮助:)

标签: c# unity3d shader


【解决方案1】:

Update() 已经“随着时间的推移”运行。您不需要 for 循环协程。您只需要跟踪在Update() 方法体内发生变化的变量。

up = Time.deltaTime * (up + 0.1f);

哦,等等,你已经做到了。

void Update()
{
    rend.material.SetFloat("_Blend1", up);
    if(switchOn == true) {
        up = Time.deltaTime * (up + 0.1f);
        if(up >= 1) {
            switchOn = false;
        }
        print(switchOn);
    }
}

塔达。

但是,您仍然需要代码来再次降低值(将其设置为 0 或只是将其设置为 0)但您的原始代码也没有它,所以我不包括它。

【讨论】:

  • 旁注:您可能想在某个时候查看Material Property Blocks。通过直接修改着色器值,您实际上是在克隆材质,这会导致内存浪费并中断批处理。
  • 感谢您的反馈 Draco - 感谢您的帮助。可悲的是,这段代码使我的系统崩溃了。我以为我很傻,但尝试了几次,它看起来很适合我。不管怎样,谢谢你和材料属性块的注意。我还有很长的路要走!
  • @MarkQuinn 删除 while 循环。我没有注意到(编辑答案)。
【解决方案2】:

Time.deltaTime 返回完成最后一帧所花费的时间,因此在您循环时它将大致保持不变(并且值非常小) - 这使您的 up 值保持很小。你应该能够像这样调整价值。

float t = 0;

void Update()
{
    if (switchOn == true)
    {
        t += Time.deltaTime;
        rend.material.SetFloat("_Blend1", Mathf.Lerp(0, 1f, t/3f)); //3 is time to complete lerp
    }
    if (t > 3) // lerp has completed. reset function and timer.
    {
        t = 0;
        switchOn = false;
    }
}

【讨论】:

  • 这非常有效。它通过使用 Lerp 回答了我的问题——这在过渡时似乎有很大帮助。我需要更多地掌握它的用途。我不必要地把它复杂化了。再次感谢您!
猜你喜欢
  • 2018-03-29
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多