Home > Net >  loop that accumulates for each call
loop that accumulates for each call

Time:01-20

I'm trying to create a stamina system that loses x amount of stamina when attacking and after 5 seconds the lost stamina is regenerated, but I can't make it so that when the function is called several times, the previous calls are deleted and only last call left

this is my function

    Debug.Log("Etapa 0");
    if(currentStamina <= maxStamina){
        StartCoroutine(TimerStamina());
        Debug.Log("Etapa 1");
    }
    IEnumerator TimerStamina(){
        yield return new WaitForSeconds(5);
         StartCoroutine(RestartStamina());
         Debug.Log("Etapa 2");
    }
    IEnumerator RestartStamina()
    {
        for(int x = 1; x <= maxStamina; currentStamina  ){
            Debug.Log("Etapa 3");
            

            yield return regenTick;

            if(currentStamina > maxStamina)
            {

                yield break;
            }
        }
        Debug.Log("Estas cansado");
        Debug.Log("Etapa 5");

}

I have tried several things but no result, so surely something is wrong with the way I am approaching this

CodePudding user response:

So if I understand correctly you want that no matter how often you hit attack, the stam regeneration only starts 5 seconds after the last attack.

There are probably many many ways to achieve this.

For instance I wouldn't use a routine at all but simply have a timer and restart it in Update like

private float regenTimer;

public void Attack()
{
    ...

    currentStamina -= someAmount;

    regenTimer = initialDelay;
}

private void Update()
{
    regenTimer -= Time.deltaTime;

    if(regenTimer <= 0 && currentStamina < maxStamina)
    {
        currentStamina = Mathf.Min(currentStamina   regenAmountPerSeconds * Time.deltaTime, maxStamina);
    }
}

or if it is not float but rather int then you could have two timers

private float regenTimer;
private float regenTickTimer;

public void Attack()
{
    ...

    currentStamina -= someAmount;

    regenTimer = initialDelay;
    regenTickTimer = regenTickDelay;
}

private void Update()
{
    regenTimer -= Time.deltaTime;

    if(regenTimer <= 0 && currentStamina < maxStamina)
    {
        regenTickTimer -= Time.deltaTime;

        if(regenTickTimer <= 0)
        {
            currentStamina  = regenAmountPerTick;
            regenTickTimer  = regenTickDelay;
        }
    }
}

If you rather want to go for a Coroutine you could store and cancel it when needed e.g.

private Coroutine regenRoutine;

public void Attack()
{
    ...

    currentStamina -= someAmount;

    if(regenRoutine != null) StopCoroutine(regenRoutine);
    regenRoutine = StartCoroutine(RegenRoutine());
}

private IEnumerator RegenRoutine()
{
    yield return new WaitFoSeconds(initialDelay);

    while(currentStamina < maxStamina)
    {
        currentStamina  = regenAmountPerSecond * Time.deltaTime;
        yield return null;
    }
}

again in case it is rather int

private IEnumerator RegenRoutine()
{
    yield return new WaitFoSeconds(initialDelay);

    while(currentStamina < maxStamina)
    {
        yield return new WaitForeconds(tickDelay);
        currentStamina  = regenAmountPerTick;
    }
}
  • Related