I have a simple coroutine that adds stacks of ‘cold’ and removes them after a period of time in order to slow the player when they are hit by a certain projectile:
public IEnumerator SlowPlayer(int numStacks, float stackDuration)
{
coldStacks += numStacks;
for (float i = 0; i < stackDuration; i += 0.1f)
{
yield return new WaitForSeconds(0.1f);
}
coldStacks -= numStacks;
}
The idea here is to add 1 stack, wait some time, and remove the stack. However, if the player gets hit again while the first coroutine is still running, it seems to abandon the first co-routine, leaving the stacks on, resulting in a permanent slow.
How can I run multiple co-routines of the same type as separate entities so they don’t interfere with one another, and I can remove the stacks after some duration?
I don’t see issue with your current code, because it’s straightforward:
Add stack;
Wait;
Remove stack.
If you will test out this code in Update with public coldStacks you will see that it increases and decreases, because Coroutines don’t disappear if you call another one.
I would only recommend remove the for loop, because your code is equal to simplified this:
yield return new WaitForSeconds(stackDuration);
Therefore the issue is probably in your actual slow code where are you checking for stacks. So, it’s hard to say exactly what you should do, since your code can be design in different ways, however, let’s look at this logic:
public int coldStacks; // Total coldStacks
public float slowTime; // Slow time
public int i; // Coroutine increase counter
Coroutine slowing;
void Update()
{
if (Input.GetKeyDown(KeyCode.B))
AddSlow(1);
}
public void AddSlow(int numStacks)
{
coldStacks += numStacks;
/* We only call new coroutine in case where the previous one already done
* Otherwise by increasing above coldStacts the current executed will simply extend it execution time */
if (slowing == null)
slowing = StartCoroutine(SlowPlayer());
}
public IEnumerator SlowPlayer()
{
/* --- Add slow debuff --- */
while (i < coldStacks)
{
yield return new WaitForSeconds(slowTime);
i++;
}
/* --- Remove slow debuff --- */
/* Reset variables */
slowing = null;
i = 0;
coldStacks = 0;
}
I wrote it so that you can place it and test by pressing B key and see the public integers increasing/resetting.
The logic of this code that we have only 1 Coroutine that represents our slow and if we already slowed (that means that we have Coroutine in execution) then we only increase coldStacks and since Coroutine is checking while (i < coldStacks) then by adding coldStacks we extend slow debuff before it will be gone.
You can then specify, adjust the functions and variables as you want.