Variables that should be limited to the scope of foreach-loops seem to "leak" inside my coroutine?

DamagesDealt is a Dictionary<string, List<DamageDealt>>, the key being a string that represents the damage type.

As you can see in the screenshots, I am at the breakpoint in the line with EndTurn. However in the locals you can see that q still exists, even though it’s from the inner foreach-loop. Also, there’s a weird local variable called ["Ice"], which appears to be one of the key-value-pairs from the outer foreach-loop.

Neither of these should exist anymore at that point.

Also, as i mentioned in the question-title, all of this is in a coroutine. Is there something weird about using foreach-loops inside coroutines that messes this up?

Or what’s going on here?

This actually seems to be causing a bug, where in the next turn… oh, i just realized that you can’t see that all of this is inside yet another loop in the coroutine. Here’s the full code:

public IEnumerator RunCombatEncounter(Game game_, CombatEncounter ce_) {
        game = game_;
        ce = ce_;
        game.eventHandler = this;
        InitializeCombatantUI();
        while (true) {
            var c = Fun.GetCharacterWhoseTurnItIs(ce);
            Debug.Log("--------- " + c.Name + " -----------------------");
            if (game.PlayerParty.Contains(c)) { // is in player party, so ask player what to do
                DisplayTurnMenu(c);
                yield return new WaitWhile(() => chosenAction == null);
                if (chosenAction.TargetType == TargetType.Hostile || chosenAction.TargetType == TargetType.Friendly) {
                    DisplayTargetChoiceMenu(c, chosenAction.TargetType);
                    yield return new WaitWhile(() => chosenTarget == null);
                }
            }
            else { //ai enemy turn
                var actions = Fun.GetCombatActions(game, ce, c);
                if (actions.Count == 1) {
                    chosenAction = actions[0]; //skip turn if all we can do.
                }
                else {
                    chosenAction = actions[Random.Range(0, actions.Count - 1)];
                    if (chosenAction.TargetType == TargetType.Hostile) {
                        chosenTarget = game.PlayerParty[Random.Range(0, game.PlayerParty.Count)];
                    }
                    else if (chosenAction.TargetType == TargetType.Friendly) {
                        var enemies = ce.Combatants.Where(e => !game.PlayerParty.Contains(e)).ToList();
                        chosenTarget = enemies[Random.Range(0, enemies.Count)];
                    }
                }
            }
            OnActionChosen(c, chosenTarget, game, ce, chosenAction);
            chosenAction = null;
            chosenTarget = null;
            foreach(var pair in DamagesDealt) {
                foreach(var q in pair.Value) {
                    SpawnDamageNumber(q.c, q.amount, pair.Key);
                }
                yield return new WaitForSeconds(0.3f);
            }
            DamagesDealt.Clear();
            Fun.EndTurn(game, ce);
            RefreshCombatantUI();
            yield return new WaitForSeconds(1);
            var combatStatus = Fun.GetCombatStatus(game, ce);
            if (combatStatus == CombatStatus.Won) {
                Debug.Log("You won!");
                lastCombatEncounterEndingStatus = combatStatus;
                Fun.EndCombat(game, ce);
                break;
            }
            else if (combatStatus == CombatStatus.Lost) {
                Debug.Log("You lost!");
                lastCombatEncounterEndingStatus = combatStatus;
                break;
            }
        }
        game.eventHandler = null;
    }

Anyway, the bug seems to be that I’m getting a key-value-pair from the last turn again, even though it shouldn’t even exist anymore, since I call DamagesDealt.Clear(); every turn. This actually seems to be that weird ["Ice"] thing I’m seeing.

Anyone know why these variables seemingly escape their scope?

Okay, so i guess it’s normal for locals in co-routines to exist outside of their scope. I thought that caused my issue, but it was actually just a dumb bug in my code:

I call DamagesDealt.Clear(); before i call EndTurn, but in EndTurn, damage can still happen if someone is on fire, so it added some fire-damage that would then exist in the next turn, but the character being damage might already be dead.

So swapping DamagesDealt.Clear(); and Fun.EndTurn(game, ce); fixed it.

Not sure if I should delete this question, since it turned out to be something completely different. :smiley: