I can not get my animation to finish before Destroy(gameObject) happens. I have googled it and so far nothing i have found has worked. Not sure if i am just doing it wrong or what.
No, i haven’t tried in the script below, starting back from I know works and going from there.
public class EnemyStats : CharacterStats
{
public override void Die()
{
base.Die();
//Add death animation here
GetComponent<Animator>().SetTrigger("die");
Destroy(gameObject);
//destroy the gameobject
//Spawn loot here
}
}
Move your call to “Destroy” to a new public function, maybe call it “OnDeathAnimationFinished”. Inside Unity, inside the “Animation” window, there is an “add event” button that allows you to call public function from components attached to the same object as the animator. You can use that to call your “OnDeathAnimationFinished” at the end of your death animation.
After you destroy the gameobject that’s it. Anything belonging to that gameobject stops. No line after Destroy() will be executed either, so your ‘spawn loop here’ should happen above the Destroy().
That said, it’s generally a bad idea to destroy gameobjects at runtime. Destroying objects causes the reference to become unused, meaning the garbage collector will eventually have to collect the memory you are not using anymore, potentially causing spikes in framerates. Instead you may want to look into a technique called Object Pooling, where you dont destroy frequently used objects (like enemies), but instead recycle them. There is no difference between destroying an enemy and spawning a new one, or disabling an old enemy and spawning it at a new location - other than the latter being faster.
As for your main problem, i would probably create a function “FinishedLifeCycle()” in the Enemy class. This function checks all relevant events, like death animations playing, and return true only after the enemy is fully not needed anymore.
While dying, put the enemy into a List dyingEnemies, which you occasionally iterate over to see which enemies can be recycled (or destroyed, if you dont want to use pooling for some reason).
Honestly never heard that about the “pooling thing”. I will have to look into that. Is that like where you have enemies saved in a “test” area and when you want them to appear you simply spawn them at the new location and when they “die” it is actually just moving them back?
I know that sounds dumb as it’s pretty much what you said, I am just wanting to make sure. A good example is like older RPG’s (i think maybe skyrim did it too) where there is a test scene with all items/enemies in it, and those are actually pulled from there.
Sort of like you described it, but not quite. The idea is that you want to prevent calls to Destroy and Instantiate as much as possible during runtime (or at least during Update), since Destroy causes garbage that needs to be collected by the GC, and Instantiate is rather expensive (especially in numbers). So if you already know you will need, let’s say, 500 enemies in your scene, you will Instantiate them all while loading and keep them disabled in some list. When you need a new enemy to spawn, you can now simply get one from that list, set it to active, change its position and … there you go, you spawned a new enemy without Instantiating it. Once you dont need it anymore, you turn it off (reset its state like HP, or do this when re-spawning it next time) and put it back into that list. It’s a bit more complicated than that, since realistically you will want to have a dynamic pool size and all that stuff, but that’s the idea behind it.
So it’s not as much a visual, accessible area where enemies wait around until they are needed, it’s rather just having them already loaded into memory if you know you will need them eventually, and then being able to access them more quickly (and not having to destroy and recreate them again at runtime).
Object pooling is a pretty common technique, even tho i didnt know about it either before coming to Unity / Game Development. You will find plenty of tutorials on it