This is my personal way of solving pooling/spawning issues. I know that I called it Enemy Pooling (which is mainly because I am using this solution for my Animal AI) but you can easily utilize it for everything else as it is written pretty generic.
How it works:
We are creating a dictionary of pools, which will hold all of the pools we need. Every pool needs his own spawner element. There are two modes for spawning objects – either “PERMANENT”, which means a new object spawns instantly if there aren’t enough active objects of that kind in the scene or “WAVE”, which only spawns a set amount(the max amount) of new enemies if all of the active enemies from before have been cleared out. For each spawn the script generates a random spawn point that is located within a given radius, checks if this spawnpoint is currently occupied with a layermask and then spawns an object there if the point is not occupied. if it is occupied the spawner will generate a new spawn point.
Adding objects back to the pool:
There are different approaches for adding objects back. You could either have the object setting itself as inactive if it is dead/deleted and then make use of an observer pattern looping through the list of active objects, sorting out all the inactive objects and removing them from the active list and adding them back to the pool. Or just cache the pool and spawner for each object and have them add/remove Themse after inactivating.