0

I have a shader in Unity that is set up to blend between two textures. This is set up and works fine.

Blend has a range from 0-1 and works well on offline mode.

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

I have set up an OnClick pointer that works fine. It essentially toggles a value to true and activates it in the Update. I have had some success on toggling the values between 0 (The first texture and 1 (The second texture).

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

In the update when switchOn is true I have a while loop that runs and increments a count for the blend.

 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);
    }
}

The trouble I am having is that the value increments are not working alongside time.deltaTime. I am seeing that Time.deltatime may not work in a while loop. So I have also tried a CoRoutine with a WaitForSeconds. None of this is giving me the incrementation that I desire.

I have looked into Lerping this - but I'm not aware how to Lerp such a value - I have been looking, perhaps in the wrong places.

Can someone point me in the right direction?

Mark Quinn
  • 79
  • 11
  • 1
    Can't believe no answer mentioned this in all these answers. The issue in your code is because your are using `Time.deltaTime` in the `Update` function which is a void function. `Time.deltaTime` will not change in the `Update` function. Move all those code into a coroutine(`IEnumerator`) function then add `yield return null` to the end of the `while` loop, your problem should be solved. – Programmer Aug 25 '17 at 17:31
  • Thank you for your comment Programmer. Right I need to read up on time.deltatime a bit more. I've been taking this for granted. – Mark Quinn Aug 25 '17 at 17:58
  • 1
    No problem. You also need to learn coroutine too since you need them when it comes to [doing something over time](https://stackoverflow.com/questions/45736799/decrease-variable-over-a-specific-amount-of-time/45737410#45737410) otherwise you do it in the Update function which will run forever instead of "run then end". Happy coding! – Programmer Aug 25 '17 at 18:04
  • 1
    I am familar with corotuines with waitforseconds - problem was it just wasn't playing ball and I wasn't seeing the problem! There was a clash. I'll get there. But thank you all the same - the responses help :) – Mark Quinn Aug 25 '17 at 18:07

2 Answers2

2

Update() already runs "over time." You don't need a for loop or a coroutine. You just need to track a variable that changes inside the Update() method body.

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

Oh wait, you already do.

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

Ta da.

However, you still need code to bring the value back down again (either animating it back to 0 or just setting it to 0) but your original code didn't have it either, so I'm not including it.

  • 2
    Side note: You may want to look into [Material Property Blocks](https://docs.unity3d.com/ScriptReference/MaterialPropertyBlock.html) at some point. By directly modifying the shader value you're actually *cloning the material* which results in memory wastage and breaks batching. – Draco18s no longer trusts SE Aug 25 '17 at 15:39
  • Thank you for your feedback Draco - your help is appreciated. Sadly this code crashed my system. I thought I was being silly but tried it out a few times and it looks appropriate to me. Regardless thank you for this and the heads up on the Material Property Blocks. Many miles for me to go! – Mark Quinn Aug 25 '17 at 16:32
  • @MarkQuinn Remove the while loop. I didn't notice it (edited answer). – Draco18s no longer trusts SE Aug 26 '17 at 07:53
2

Time.deltaTime returns the time it took to complete the last frame so it will be roughly constant as you loop through (and a very small value) - which is keeping your up value to remain tiny. You should be able to lerp the value like so.

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;
    }
}
ryeMoss
  • 4,303
  • 1
  • 15
  • 34
  • This worked perfectly. It answered my question by ustilising the Lerp - which seems to be a big help when transitioning. I need to grasp it's uses more. I needlessly complicated it. Thank you again! – Mark Quinn Aug 25 '17 at 16:32