InvokeRepeating work only once

Hi everyone, i read some posts here and in other forums but i don’t understand how to use InvokeRepeating.

public class LightMovements : MonoBehaviour
{

public Light myLight;
private float maxRange = 25;
private float minRange = 13;
private float maxIntensity = 5;
private float minIntensity = 4;
private float midRange = 19;
private float midIntensity = 4;
private bool timerDecrease = false;

[SerializeField] float timer;

void Start()
{
    myLight = GetComponent<Light>();   //Gli passiamo il componente luce        
    timer = 0f;
}

void Update()
{
    if (Input.GetKey(KeyCode.E))    //Utilizziamo la E per incrementare i parametri della luce 
    {
        timer += Time.deltaTime;
        if (timer >= 0.5f)
        {
            myLight.intensity = maxIntensity;
            myLight.range = maxRange;
        }
    }

    if (Input.GetKeyUp(KeyCode.E))   //A regola nel momento in cui alzi il dito dalle E abbassa tutto 
                                        // nel giro di qualche secondo, peccato lo faccia solo la prima volta circa
    {
        if (!IsInvoking("RangeDecreaser"))
        {
            InvokeRepeating("RangeDecreaser", 0.6f, 0.1f);
        }
        if (!IsInvoking("IntensityDecreaser"))
        {
            InvokeRepeating("IntensityDecreaser", 0.6f, 0.6f);
        }
        timer = 0;

    }
    
    if (Input.GetKey(KeyCode.Q))      //Utilizziamo la Q per diminuire i parametri della luce 
    {
        timer += Time.deltaTime;
        if (timer >= 0.5f)
        {
            myLight.intensity = minIntensity;
            myLight.range = minRange;
        }

    }

    if (Input.GetKeyUp(KeyCode.Q))   //Stessa cosa delle E ma aumentiamo a regola
    {
        if (!IsInvoking("RangeIncreaser"))
        {
            InvokeRepeating("RangeIncreaser", 0.6f, 0.1f);
        }
        if (!IsInvoking("IntensityIncreaser"))
        {
            InvokeRepeating("IntensityIncreaser", 0.6f, 0.6f);
        }
        timer = 0;
    }

}
void RangeDecreaser()
{
    while (myLight.range > midRange)
    {
        myLight.range -= 1;
    }
  
}

void IntensityDecreaser()
{
    while (myLight.intensity > midIntensity)
    {
        myLight.intensity -= 1;
    }
}

void RangeIncreaser()
{
    while (myLight.range < midRange)
    {
        myLight.range += 1;
    }
}

void IntensityIncreaser()
{
    while (myLight.intensity < midIntensity)
    {
        myLight.intensity += 1;
    }
}

}

This is my script. What I would like is that after the light has increased its parameters, after a few tenths of a second it returns to mid values. I tried it with Invoke but it works the first time then the others repeats at every frame. Can you advise me how to correct this or maybe you have to advise me in some smarter way? thank you so much,

If you have while loops in your coroutine make sure that you also use yield return if you want the while loop to run over time. Currently,

void RangeDecreaser()
{
while (myLight.range > midRange)
{
myLight.range -= 1;
}

}

Just executes the whole while loop all at once. If you want your while loop to run over time then use a yield return null, which basically just means “ok I’m going to stop executing for now and I’ll pick back up where I left off on the next update frame”

 while (myLight.range > midRange)
 {
     myLight.range -= 1;
     yield return null;
 }

However, you are using InvokeRepeating, which means that Unity is going to repeatedly call your function. If this is what you want to do, you shouldn’t have a while loop at all because InvokeRepeating will call the function again for you. Just change it to an if condition

 if (myLight.range > midRange)
 {
     myLight.range -= 1;
 }

So either use just Invoke with a while loop and a yield return, or use InvokeRepeating with an if statement. If you want to use the first method with yield return, you can control the timing between calls by returning WaitForSeconds instead, so to match the frequency of your InvokeRepeating call you would say

 while (myLight.range > midRange)
 {
     myLight.range -= 1;
     yield return new WaitForSeconds(0.1f);
 }