Mine is an open-world game, I don’t have machine gun bullets, but I do have a lot of monsters and objects that come on and off as the player moves around and terrains are generated / destroyed. I’ve never used pooling because I’ve never really had a problem with anything and I’ve a ways until I start optimizing for version 1.0. Having said that I started looking into pooling after a conversation about it started and I’ve found some interesting results.
This is using an animated SkinnedMeshRenderer .
I’m pulling from the pool, or instantiating, 50 at a time and repositioning them randomly until 5,000 objects have been used. So that’s 5,000 Instantiate() and Destroy() or the repeated reuse of a pool of 50 GameObjects. I do the 5,000 loop for 10 iterations and then average the time it took across all ten iterations to create a final average time, all within a single frame:
Pool using GameObject.SetActive true/false: 2.244811 (310x)
Instantiating and Destroying with forced GC.Collect per iteration: 0.8234555 (114x)
Instantiating and Destroying with no GC.Collect: 0.7385982 (102x)
Pool using Component.enabled true/false: 0.007248688 (1x)
Pool with no enable/disable: 0.002649307 (0.37x) (I consider this impractical)
If you believe what your average random Unity blog or YouTube video tells you they generally say to SetActive(false) and return objects to the pool, but according to this test that’s actually slower than simply instantiating and destroying.
Of course the “real” benefit of pooling is supposed to be the reduction of garbage generated and then picked up by the GarbageCollector, which i know very little about, so I may not be seeing the real results of GC in runtime, but the performance increase generated by component caching instead of using SetActive is 310x. Given there are only 2 components in this test, and I certainly don’t instantiate 5,000 objects in a single frame, but that’s a big difference.
I’ve attached the script in case I’m doing something incorrect.
I’m imagining a component directly beneath the Transform with references to all further components that should be turned on/off when leaving or returning to the pool would reduce realtime uses to a single GetComponent during runtime instantiation and storing each type of prefab in dictionaries with enumerator keys and GameObject[ ] pools, sized to fit different probable uses, like 10, 50, 100.
If anyone could enlighten me further on this subject I would appreciate it. Or offer any further pointers I’d appreciate it.
5113976–504869–Pooltest.cs (4.93 KB)