So I don’t know why no one else is encountering this. The closest example was this bug but it was only for projectiles.
So what happens is
- Enemy 1’s Fighter.Hit is called via the animation event
- This calls Health.TakeDamage() on the player
- The player is not dead yet so the player takes damage then dies. The die event triggers
- Respawner picks this up and starts the respawn routine which heals the player and begins fading out
- The respawn routine ends
- The next enemy’s animation event triggers. It seems because this was triggered before the frame ended it takes place as if everyone is still in their non-prespawned location. Because the player was healed that means the player can take damage again, which then triggers the die event again which triggers respawner again which includes another fade out, heal, etc
- The next enemy’s animation event triggers… you see where this is going
So what it seems we need is some way to mark the character as being in a “respawning” state so that the next Hit() events from the enemies have no effect.
Or maybe we have to delay the player’s heal with a coroutine so that it happens in a future frame thus making an upcoming Health.TakeDamage() terminate early.
I have to admit the mix of coroutines and animation events creates a code flow that is a little tough to fully diagnose.
I tried the following trick (see first line of RespawnRoutine) to cancel all the enemy attacks but it seems the update loop then gives them another target again. So I’m thinking we need some sort of two stage action to entirely suspend the enemy AIControllers and only reenable them once we’re sure the respawn routine has completely concluded.
But I’m also more than willing to bet I have some other bug somewhere.
private IEnumerator RespawnRoutine()
{
CancelEnemyActions();
SavingWrapper savingWrapper = FindObjectOfType<SavingWrapper>();
savingWrapper.Save();
yield return new WaitForSeconds(respawnDelay);
Fader fader = FindObjectOfType<Fader>();
yield return fader.FadeOut(fadeTime);
RespawnPlayer();
ResetEnemies();
savingWrapper.Save();
yield return fader.FadeIn(fadeTime);
}
private void CancelEnemyActions()
{
foreach (AIController enemyController in FindObjectsOfType<AIController>())
{
Health health = enemyController.GetComponent<Health>();
if (health && !health.IsDead())
{
health.GetComponent<ActionScheduler>().CancelCurrentAction();
}
}
}