Can't Stop couroutines

Hi there, I’m trying to make a game where when you are near a FireCamp, you gain HP, and else, you lose HP (like a survival game).

My code was working just fine (like a week ago), and I modified a couple of stuffs, not really in link with the HP, and the moment I put a UI with a HP Bar, I’ve realised that the moment I happen to be near a FireCamp, I’m losing HP and winning HP at the same time, and when I go out of the healing zone, I still win HP (which was not the case 1 week ago). I’ve deleted everything and wrote back everything and I still have the problem. I can’t find a proper way to debug it either. Here is my code :

void Update () {

    if (isInZone)
    {
        _startWinningLife = true;
        _startLosingLife = false;
    }
    else if (!isInZone)
    {
        _startLosingLife = true;
        _startWinningLife = false;
    }
    LifeManagement();
}

// Manages all the states of Life Alterations 
void LifeManagement()
{
    if (_startWinningLife)
    {
        if (!_isWinningLife)
        {
            WinLife();
        }
        _startWinningLife = false;
    }
    if (_startLosingLife)
    {
        if (!_isLosingLife)
        {
            LoseLife();
        }
        _startLosingLife = false;
    } 
// Starts the losing hp cycle and stops the winning hp cycle
void LoseLife()
{
    _isWinningLife = false;
    StopCoroutine(LifeWinning());
    _isLosingLife = true;
    StartCoroutine(LifeLosing());
}

// Player loses Hp every Seconds
IEnumerator LifeLosing()
{
    yield return new WaitForSeconds(1);
    _hp = _hp - _overtimeDamage;
    yield return StartCoroutine(LifeLosing());
}

// Player wins Hp every Seconds
IEnumerator LifeWinning()
{
    yield return new WaitForSeconds(1);
    _hp = _hp + _overtimeHeal;
    yield return StartCoroutine(LifeWinning());
}

Can someone please help me?

Thanks a lot

Yes, the problem here is that , the code you wrote isn’t the correct way to stop a coroutine. These lines are the problem (39 and 41):

StopCoroutine(LifeWinning());
StartCoroutine(LifeLosing());

Coroutines are a special objects. These are called generators in C# and many other languages, but I’ll stick to the point. The way you create a Coroutine (Generator) is by calling the method that returns an IEnumerator instance which is what you put inside a StartCoroutine method call. This IEnumerator method it’s kind of like a constructor, so what you are doing basically is trying to stop an instance of a new coroutine, it’s like if you expected this to work.

SpawnMethod( new CoolObject());
Destroy( new CoolObject());

Do you think the Destroy method will the destroy the same object that was passed to the Spawn method? No it won’t, because they are referring to 2 completely different objects and that’s what’s happening in your code right now.

If you want to stop a specific instance of a coroutine you will need to save it on a field. So what you should do is add 2 fields like this:

private IEnumerator lifeLosingCoroutine;
private IEnumerator lifeWinningCoroutine;

Then when you start these coroutines you first save the object returned by the IEnumerator methods on to these fields and then you use StartCoroutine with these fields as the parameters, like this:

lifeLosingCoroutine = LifeLosing();
StartCoroutine(lifeLosingCoroutine);
//Same thing for the life winning one

//And then you would stop it like this
StopCoroutine(lifeLosingCoroutine);
lifeLosingCoroutine = null;
//And same thing for the life winning one

Hope this helps!