- Home /
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
You may also stop a couroutine by starting it with
StastCorountine("$$anonymous$$yCoroutine$$anonymous$$ethodName");
//and stoping it with StopCoroutine("$$anonymous$$yCoroutine$$anonymous$$ethodName");
But this will stop ALL coroutines initiated with this way.
Answer by MacDx · Oct 17, 2017 at 05:09 AM
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!
That helps a lot! I'm not sure if the correction is right (though I'm pretty sure it is) as I will have to correct it when I'll be home, but it looks like that does make sense.
Your explaination makes a lot of senses to me, and I appreciate it! So, just to be sure I got it right, If I would put StopCoroutine(coroutine()); It would create a coroutine, then stop it immediately?
Thanks a lot for this!
It would create a coroutine, then stop it immediately?
Yup, which isn't very useful
Ok I just checked out the code and I still have problems.
First, I got a null reference, because at the start of the game, both IEnumarator are set to null so it can't stop a null IEnumerator. So, I put a Null Check to be sure that's not the case when I happen to stop the coroutine. Yeah for me! It works now!
BUT! I still have the same problem as before : The moment I go near a Fire Camp, my HP starts to go up, but I still lose HP too.... I've put a Debug.Log to check if I go pass the null check to stop a coroutine, and the Log appears to work fine. But, for a reason, the Coroutine does not seems to stop? Is that possible? I've put the StopCoroutine in a String format, which should in theory stop every Coroutine with the String name, and nothing happens neither....
I'm crying inside right now. It's a custom game I had to make for a class (which I should give to the $$anonymous$$cher tomorrow night), and that is the last thing I need to do...and the first I did back when it worked....
If you know what is going on... I'd be thanksfull senpai!