I am trying to take away some health from a slider using a coroutine, but it takes away too much

Hi, I’m trying to on button press (CardBoyAttack) trigger a bool to be true (isActivated) which starts a coroutine to take away some health from each slider. However when the coroutine is started, it subtracts 1000 health from each healthbar in one second. I have no idea why this is happening. Here is my code:

using System.Collections;

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class MoveCardBoy : MonoBehaviour
{
public bool IsActivated = false;
public Vector2 newPosition;
public Vector2 originalPosition;
public Button AttackButton;
public SpellFireSpirit fireSpiritScript;
public float playerattackValue;
public float enemyAttackValue;
public bool isAttacking = false;

 void FixedUpdate()
{
    if (IsActivated) 
    {
        transform.position = newPosition;
        
        StartCoroutine(ReturnToPosition());
    
    
    }
    
}

IEnumerator ReturnToPosition() 
{
    yield return new WaitForSeconds(1f);
    fireSpiritScript.enemyHealth = fireSpiritScript.enemyHealth - playerattackValue;
    Debug.Log(fireSpiritScript.enemyHealth.ToString());
    fireSpiritScript.playerHealth = fireSpiritScript.enemyHealth - enemyAttackValue;
    Debug.Log(fireSpiritScript.playerHealth.ToString());
    isAttacking = false;       
    transform.position = originalPosition;
    IsActivated = false;
    AttackButton.interactable = true;
    


}

public void CardBoyAttack() 
{

    IsActivated = true;
    AttackButton.interactable = false;

}

}

The problem is that you’re starting your coroutine in the FixedUpdate method. Coroutines are different to functions in the regard that all code after it runs regardless of whether the coroutine has finished or not.


This means that even though the coroutine hasn’t finished yet, you can still run it again and again simultaneously, which seems to be what you’re doing here, every fixed update, which drains more health than it needs to.


To fix this, you can use a bool to keep track of whether the coroutine has finished or not. Here’s the new code:

bool CoroutineIsFinished = true; 

void FixedUpdate()
 {
     if (IsActivated && CoroutineIsFinished) 
     {
         transform.position = newPosition;
         
         StartCoroutine(ReturnToPosition());
     
     
     }
     
 }
 IEnumerator ReturnToPosition() 
 {
     CoroutineIsFinished = false;

     yield return new WaitForSeconds(1f);
     fireSpiritScript.enemyHealth = fireSpiritScript.enemyHealth - playerattackValue;
     Debug.Log(fireSpiritScript.enemyHealth.ToString());
     fireSpiritScript.playerHealth = fireSpiritScript.enemyHealth - enemyAttackValue;
     Debug.Log(fireSpiritScript.playerHealth.ToString());
     isAttacking = false;       
     transform.position = originalPosition;
     IsActivated = false;
     AttackButton.interactable = true;
     
      CoroutineIsFinished = true;
 }
 public void CardBoyAttack() 
 {
     IsActivated = true;
     AttackButton.interactable = false;
 
 }

@ethanol3310