MathF.Lerp in a CoRoutine

So I have this following rain script. The idea is I want it to rain every few mins for a few mins and the intensity of the rain increases over a certain number of mins and decreases over the same amount of time.

1)I have used Vector3.Lerp in similar fashion before and it works fine. But Mathf.Lerp doesnt for some reason.
The change in value is very weird.
2) i want to run the rain game object off when the rain intensity gets close to zero and NOT before that but it shuts off before that.

Would love some guidance on what i am missing here on the logic.

While i really would love to make this in a co-routine, any suggestions on how to do this in Update is also welcome.

Quick way to recreate the problem with this script would be to attach an audio to an a gameobject and instead of use intensity, use the volume.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class RainControl : MonoBehaviour {
    public GameObject RainMain;

    public float RainDuration = 40.0f;
    public float NoRainDuraion = 15.0f;
    public float RainRampDuration = 5.0f;
    // Use this for initialization
    void Start () {
        if (RainMain.gameObject.activeInHierarchy)
            RainMain.SetActive(false);
        RainMain.GetComponent<RainScript>().RainIntensity = 0;
       
    }
   
   

    private void Update()
    {
        if (!RainMain.activeSelf)
            StartCoroutine(CallTheRainGods());
    }
    IEnumerator CallTheRainGods()
    {
        yield return new WaitForSeconds(NoRainDuraion);
        StartCoroutine(IncreaseRain(0, 1, RainRampDuration));
       
        yield return new WaitForSeconds(RainDuration);
        StartCoroutine(DecreaseRain(1, 0, RainRampDuration));
       
    }
    IEnumerator IncreaseRain(float start, float end, float duration)
    {
        RainMain.SetActive(true);
        RainMain.GetComponent<RainScript>().RainIntensity = 0;
        float timestep = 0;
        while(timestep <=duration)
        {
            timestep = timestep + Time.deltaTime;
            float step = Mathf.Clamp01(timestep / duration);
            RainMain.GetComponent<RainScript>().RainIntensity = Mathf.Lerp(start, end, step);
            yield return null;
        }
    }
    IEnumerator DecreaseRain(float start, float end, float duration)
    {
       
        float timestep = 0;
        while (timestep <= duration)
        {
            timestep = timestep + Time.deltaTime;
            float step = Mathf.Clamp01(timestep / duration);
            RainMain.GetComponent<RainScript>().RainIntensity = Mathf.Lerp(start, end, step);
            if (RainMain.GetComponent<RainScript>().RainIntensity < 0.01f)
                RainMain.SetActive(false);
            yield return null;
        }
       
    }
}

You’re starting the coroutine a bunch of times, one for every frame that occurs during the start of your “CallTheRainGods()” coroutine during the WaitForSeconds(NoRainDuration).

This is because the first thing it does is yield, rather than toggle the RainMain.activeSelf bool.

1 Like

The problem appears to be that you are starting the CallTheRainGods coroutine multiple times until you set the gameobject active. Try this, I’ve also cleaned it up a bit and cached references;

public class RainControl : MonoBehaviour
{
    public GameObject RainMain;

    public float RainDuration = 40.0f;
    public float NoRainDuraion = 15.0f;
    public float RainRampDuration = 5.0f;

    private RainScript _rainScript;
    private WaitForSeconds _noRainDuration;
    private WaitForSeconds _rainDuration;

    private void Start()
    {
        if (RainMain.gameObject.activeInHierarchy)
            RainMain.SetActive(false);
        _rainScript = RainMain.GetComponent<RainScript>();

        _rainScript.RainIntensity = 0;

        _noRainDuration = new WaitForSeconds(NoRainDuraion);
        _rainDuration = new WaitForSeconds(RainDuration);

        StartCoroutine(CallTheRainGods());
    }

    private IEnumerator CallTheRainGods()
    {
        while (true)
        {
            yield return _noRainDuration;
            StartCoroutine(IncreaseRain(0, 1, RainRampDuration));

            yield return _rainDuration;
            StartCoroutine(DecreaseRain(1, 0, RainRampDuration));
        }

    }

    private IEnumerator IncreaseRain(float start, float end, float duration)
    {
        RainMain.SetActive(true);
        _rainScript.RainIntensity = 0;
        float timestep = 0;
        while (timestep <= duration)
        {
            timestep = timestep + Time.deltaTime;
            float step = Mathf.Clamp01(timestep / duration);
            _rainScript.RainIntensity = Mathf.Lerp(start, end, step);
            yield return null;
        }
    }

    private IEnumerator DecreaseRain(float start, float end, float duration)
    {

        float timestep = 0;
        while (timestep <= duration)
        {
            timestep = timestep + Time.deltaTime;
            float step = Mathf.Clamp01(timestep / duration);
            _rainScript.RainIntensity = Mathf.Lerp(start, end, step);
            if (_rainScript.RainIntensity < 0.01f)
                RainMain.SetActive(false);
            yield return null;
        }

    }
}
1 Like

thank you @Kurt-Dekker & @WarmedxMints_1 . I see the error in my ways now.

would yield return null be the same as using yield break? thank you for taking the time to fix the code btw.

No, they are quite different. break does as it sounds and breaks out of the coroutine.

1 Like