It should still work. The first time the ‘on collision’ callback is called, the damage is applied, and the enemy is added to the ‘recent damage’ list. The next time the ‘on collision’ callback is called (even if it’s within the same frame), the enemy is found in the ‘recent damage’ list, and damage is not applied.
In fact, the fact that the enemies are destroyed when they run into the player makes it even easier, as you can dispense with the time stamp and just maintain a container of enemy references that’s cleared every update.
The only potential issue I can think of here is that when considering events that occur within a single game update, the order in which Unity does things ‘under the hood’ comes into play. I’d be willing to bet that if you clear out the ‘recent damage’ enemy container in the FixedUpdate() function, everything would work as expected. (This is based on the assumption that collision callbacks only occur when the physics system is updated, which only happens during fixed updates.) Or, if you wanted to be safe, you could clear the container in Update().
To summarize the method I’m suggesting, in your ‘player’ class/script you would have a list of enemy references, e.g. (pseudocode):
list<Enemy> recentDamageList;
In your Update() or FixedUpdate() function, you clear this list (again, this is just pseudocode):
recentDamageList.clear();
Your ‘apply damage’ function would then look something like this:
void ApplyDamage(Enemy enemy)
{
if (!recentDamageList.Find(enemy)) {
recentDamageList.Add(enemy);
enemy.Destroy();
health -= enemy.damage;
}
}
I can’t guarantee this solution 100%, but I’m pretty sure it’s the right idea.
Actually, here’s one more suggestion, which actually might be easier to implement:
I’m guessing that when you destroy a game object in Unity, it’s not actually removed until the end of the update; as such, removing a game object doesn’t prevent it from interacting with other objects and generating additional collisions within the same update (as you’re discovering).
However, you could simply add a ‘flagged for removal’ variable to the enemy class, and set it to true when a collision occurs. Your code would now look something like this:
void ApplyDamage(Enemy enemy)
{
if (!enemy.flaggedForRemoval) {
enemy.Destroy();
enemy.flaggedForRemoval = true;
health -= enemy.damage;
}
}
This would most likely be both more efficient, and easier to code.