Pro Pooling


Pro Pooling is the go to solution for simple yet powerful pooling and spawning in Unity. Designed from the ground up to increase game performance and save development time, Pro Pooling provides a comprehensive yet easy to use system for pooling including configurable pools, and powerful object spawning and despawning.

As the number of items in your game increases, performance can take a serious hit, especially when these items are dynamically created and destroyed such as enemies, projectiles, bullets, collectables or other items. Pooling is the concept of pre-allocating and reusing items and is essential for fast game performance to avoid high overheads caused by continuously creating, initialising and destroying gameobjects. Pooling is an essential part of any game that allows for faster and smoother performance and when implemented using with Pro Pooling can help drastically increase your productivity.

Features include:

  • Speed up your games and save memory with fast prefab pooling.
  • Easy to use.
  • Create pools through the Unity Editor, with code or automatically.
  • Global and per-scene pools
  • Dynamic Pools.
  • Advanced automatic spawning of items.
  • Full pool lifecycle notifications to manage your pooled items.
  • Generic based pool items to help you manage per pooled item configuration, settings and data making things even faster.
  • Pool event components to help work with pooled items and automate despawning.
  • Integrated and works with Game Framework (free and extras bundle).
  • Designed for all platforms, optimised for mobile.
  • Full API.
  • Full documentation and support
  • and more…

Download now from the Unity Asset Store, or get it as part of the Game Framework Extras Bundle (upgrade option also available).

Quick Start Guide

A more detailed description follows below, however to get started quickly with a basic scenario, use the following simple steps:

  • Import Pro Pooling into your project.
  • Create a Gameobject in your scene and add the Global Pools component.
  • Drag the prefabs that you want pooled onto Global Pools
  • Add a Spawner component and drag in the same prefab to show pooled items.

Demos

There are also additional demos included in the asset that help show how to use various features of Pro Pooling.

Tutorials

Key Concepts

The following is a brief overview of some key concepts that you should familiarise yourself with to understand and get the most out of Pro Pooling. Further details are provided later in this document.

  • Pool – The concept of a Pool lies at the heart of Pro Pooling. A Pool contains a number of pre-allocated instances (gameobjects) of a specified prefab that can be reused. You can create as many different pools as you need for each of the prefabs that you need to use in your game, each with their own settings. Pools can be easily created through the editor by adding them to the Global Pools or Pools components or can be created with a single line of code. A Pool has many options for setting the number of pre allocated instances, how the pool size may change over time and more.
    (API)
  • Global Pools – The Global Pools component provides an easy way to setup, reference and monitor pools through the Unity Editor. It works with other components such as Spawner for code free pooling whilst also providing many methods for accessing and working with the pools from code for more advances requirements. Global Pools remain active and available across scene changes so should be placed on a unique GameObject (or one that is expected to survive across scene changes).
    (API)
  • Pools – Often you will want pools to only be active for a particular scene so that they don’t unnecessarily take up memory when not needed (e.g. you probably don’t need a pool with 100 bullets active on a static title scene). Pools configured directly through the Global Pools component will remain active across scene changes and thus are not suited for such non persistent pools. The Pools component is similar to the Global Pools component but it does not persist across scenes and the pools it defines will only be active whilst the Pools component itself is active. This allows for finer control on the life cycle of pools without resorting to coding.
    (API)
  • Spawner – Spawning involves removing items from a pool and placing them within your scene. The Pro Pooling Spawner component works with the GlobalPools and Pools components to automatically spawn items from a configured pool. You can configure amongst other things the prefab(s) to use, how many items to display, how often to display items, the position to display items and much more.
  • (API)
  • Despawn – Desspawning is the process of removing an item from the scene and placing it back onto a pool for others to use. Pro Pooling has several despawn components to despawn on different conditions such as when a time limit expires or when a collision occurring. You can also use our free Game Framework asset to setup advanced actions to take when despawning.
  • PoolItem – Internally a Pool holds additional meta data about each pooled gameobjects through the PoolItem class. When retreiving and returning items from / to a pool you can opt to either obtain the PoolItem, which is usually recommended as it provides cached references for speed, or work with the gameobject directly. From code you can subclass PoolItem and use the PoolGeneric class if you need to work with and cache your own custom per item values.
    (API)
  • Zombies – Beware the zombies! A zombie is a pool item that has been spawned from a pool and then destroyed rather than despawned. This leads the pool to believe that the item is still in use, and if not managed can eventually cause a pool to run out of items or hold unnecessary memory. GameObjects will be automatically destroyed when a parent gameobject is destroyed, or its containing scene is unloaded. When using the Spawner component, Pro Pooling by default leaves spawned items parented to the Global Pool / Pools component from which items are fetched to minimise the risk of zombies. When designing your game pay careful consideration to these facts and consider where to parent spawned items considering the lifecycle of the pool and any parent gameobjects.
  • IPoolComponent – If your pooled Gameobjects need to react to lifecycle events then any component you write can implement the IPoolComponent interface and be notified when an item is spawned ot despawned to perform any setup, cleanup or other needed actions. References to such components are cached within PoolItem objects for speed of access.
    (API)
  • PoolItem Components –  When items are spawned / despawned you might need to reset certain values. One example would be to reset the RigidBody velocity so that a spawned item doesn’t automatically move with the same velocity as the last time it was spawned. There are several PoolItem components that allow for initialising and resetting a number of such common properties. You can easily create new such components using the IPoolComponent interface described above.

Basic Scripting Setup

Whilst you can do many great things in Pro Pooling without ever leaving the editor, several of the below topics touch on scripting and the Pro Pooling API. A fuller description on using the API follows later, however please note already now that that to access the Pro Pooling classes from script you will need to add the following using statements at the top of your c# code files.

Setting up Pools With Global Pools

Global PoolsThe Global Pools component provides an easy way to setup, reference and monitor pools through the Unity Editor. It works with other components such as Spawner for code free pooling whilst also providing many methods for accessing and working with the pools from code for more advances requirements.

Setup and Usage

Add the Global Pools component to a gameobject within your scene by selecting Add Component | Pro Pooling |Global Pools. Next set up the pools that you need by dragging prefabs onto the drop area as suggested or clicking the Add Pool button. All assigned prefabs should ideally be uniquely named so that you can access the pools within GlobalPools by name.

Global Pools and it’s associated pools will remain active across scene changes so should be placed on a unique GameObject (or one that is expected to survive across scene changes).

Once setup and configured you can use the Spawner component described below to automatically or reactively spawn items into your scene, or interact with the Global Pools through code.

Properties

Automatically create missing runtime pools – If this option is selected then an attempt is get a pool for a prefab that isn’t configured will cause a new pool to be automatically created according to the default settings. This can remove the need for initial configuration, however should be used with care as pools will be created on the fly which can in cases of heavy load cause slowdown.

Default Pool Settings – Contains default pool settings used when creating new pools, either through the editor, automatically or through code. Further description of the individual settings is below.

For each pool, including the default settings, the following properties are available:

Prefab – The prefab that this pool is for.

Initial Size – The initial pool size (number of pooled instances) that should be automatically created and ready when the pool is initialised (at the game start). Pre initialising a pool with items in this way avoids the overhead of creating these during your game. You should initialise this around the maximum that you expect to be needed at any one time, considering the below options and other constraints.

If Size Exceeded – Defines the behaviour when an attempt is made to spawn an item from the pool and there are no inactive items left (i.e. all items are already spawned and in use). You can chose to

  • Increase the Pool Size – To create and add new items to the pool increasing it’s size.
  • Create Non Pool Items – To instantiating new items which will be destroyed when despawned and so the pool size won’t change.
  • Return Null – Returns null to any caller to indicate there are no items left to spawn.
  • Recycle Oldest – To Despawn the item that has been active the longest and reuse that.

Limit the Max Pool Size – If using an If Size Exceeded mode of Increase the Pool Size, then this option controls whether there is a maxmum limit on the pool size, or if the pool can grow in size to accommodate as many items as needed. If you enable this option then you will be able to specify the maximum size for the pool.

Create non pool items if limits exceeded – If a pool maximum size is set and this limit is also met, then this option defines what behaviour to take. If enabled then non pool items will be instantiated on the fly allowing you to handle ‘peaks’ without holding on to unnecessary memory. Alternatively a null value will be returned to the caller.

Progressive Fill – To allow the pool to be progressively filled over a number of frames to help cut down on the startup time. When enabled you can specify the amount to initially create on startup and the amount that should be created for a given frame interval, upto the on the pools initial size.

Scripting

Accessing GlobalPools

GlobalPools works as a global singleton and so only one copy is guaranteed to exist at any time. Because of this you can access the GlobalPools at any time from code through the GlobalPools.Instance reference.

It should be noted that the GlobalPools is setup in the Unity Awake() method and so you be sure it is setup before using it. You can do this in several ways including increasing the Global Pools Script Execution Order to make the Awake method of GlobalPools run before other scripts, only accessing the pool in Start() or later, or testing the GlobalPools IsInitialised property which is only set to true once initialisation has completed.

Accessing GlobalPools Pools

You can check for the existance of pools in the GlobalPools with the ContainsPool() methods, passing in a prefab or string representing the prefab name.

Use the GlobalPools GetPool() methods to retrieve a reference to an existing Pool, passing in a prefab or string representing the prefab name. GetPool() can optionally automatically create pools based on parameters or the GlobalPools configuration.

Once you have a reference to a pool you can use the different Pool methods described under the section on scripting for things like spawning and despawning.

Creating Pools

In addition to setting up pools through the editor interface, you can additionally create GlobalPools managed pools from code by calling CreatePool() passing in similar parameters to those mentioned above.

You can also call GetPool() with the autoCreate parameter set to true to have a pool automatically created, or use the AddPool() method to add a previously created Pool class. Conversly there is a RemovePool() method for removing a pool from the GlobalPools.

Spawning and Despawning

GlobalPools provides Spawn, SpawnPoolItem and Despawn methods for spawning items from and returning them to the managed pools. These methods take a prefab or pool name and then spawn / despawn from the corresponding pool. Due to the need to lookup the pool each time there is a very slight overhead to these methods. In cases where you will make frequent use of the pools it is worth calling GetPool() as shown above to cache and working against the returned Pool reference directly. A closer discussion on spawning directly from Pools follows later.

Further Information

Adding Per Scene Pools

PoolsPools configured directly through the Global Pools will remain active across scene changes and are not suited for short lived or non persistent pools. Often you will want pools to only be active for a particular scene so that they don’t unnecessarily take up memory when not needed (e.g. you probably don’t need a pool with 100 bullets active on a static title scene).  The Pools component contains similar options to Global Pools but it does not persist across scenes and the pools it defines will only be active whilst the Pools component itself is active. This allows for finer control on the life cycle of pools without resorting to coding.

Setup and Usage

Add the Pools component to a gameobject within your scene by selecting Add Component | Pro Pooling | Pools. Similarly with Global Pools, set up the pools that you need by dragging prefabs onto the drop area as suggested or clicking the Add Pool button. All assigned prefabs should ideally be uniquely named so that you can access the pools by name.

When the Pools component is enabled and active within your game, the pools it contains will be available for use. Similarly when the Pools component is destroyed the corresponding pools will also be destroyed.

Properties

Add pools to GlobalPools – If selected then pools will be automatically added to and available through the GlobalPools component for the lifetime of the Pools component. This can simplify access however care should be taken not to add duplicate pools, or those with the same name as an existing pool.

The other properties for the Pools component are similar to those defined under Setting up Pools With Global Pools. Please refer that section for details.

Scripting

Accessing Pools

You will need to get a reference to the Pools component to work programatically with the pools that are setup. You can do this by calling GetComponent<Pools>() or adding a public Pools variable to your component and dragging in a reference to the intended Pools target.

Other functionality such as that for accessing pools and spawning / despawning is the same as with GlobalPools as both inherit from the same base class, so please refer that section for further details.

Further Information

Spawning Items

Spawning involves taking items from a pool and placing them within your scene. The Pro Pooling Spawner component works with the Global Pools and Pools components to automatically spawn items into your scene from a configured pool.

In the spawner you can configure amongst other things the prefab(s) to use, how many items to display, how often to display items, the position to display items and much more. The different options are described below.

Setup and Usage

With a Global Pools pool setup, create a new gameobject at the position you want to spawn items and add a Spawner component to a new gameobject within your scene by selecting Add Component | Pro Pooling | Spawner.

Under the Prefabs section of the Spawner component, select a prefab that has also been added as a pool in Global Pools. If you run the scene now the prefab should be spawned according to the default settings. You can modify the spawn behaviour in a number of ways as described below.

Properties

Spawn From – This option lets you specify whether to spawn items from the Global Pool, a specific Pools component, or Instantiate items on the fly without any pooling.

Automatically Run – Sets whether spawning should automatically start running then the spawner is activated (and if so also giving an optional delay before it starts). If you set this option to Never then you must trigger spawning through the Spawner components StartSpawning() method.

Spawn For – Lets you specify how long the spawner should continue spawning items for. This can be Forever, or limited to a Given Number of Times or a Given Number of Seconds. If not looping forever then once any limit has been reached spawning will automatically stop unless the Loop When Done setting is enabled in which case the spawning will loop.

Spawn Interval – How long to wait before spawning the next item. This can either be a constant number of seconds or a random delay between specified minimum and maximum values.

Bursts – In addition to the standawd spawning rate lets you specify bursts of items that should be spawned at specified times.

 

Prefabs – This is where you can add the prefabs that should be looked up from the Global Pools and spawned. You should have at least one prefab added, but can have several. When multiple prefabs are added the order that they are spawned is chosen using the Select dropdown. The select dropdown contain options to chose the prefabs in order, randomly or randomly according to given weights that you can set for each prefab.

Location – This is where you can specify where items should be spawned. You can chose to have items spawned at the same location as the spawner, by specifying x, y, z positions relative to the spawner or by giving transforms that represent the spawn location(s). If specifying locations or transforms you can chose the order in which they are chosen using the select dropdown. The select dropdown contain options to chose the locations in order, randomly or randomly according to given weights that you can set for each location.

In addition for each location you can specify the spawn area size which gives the dimensions of a box around the chosen spawn location from where the final location is randomly determined. With a spawner selected, you will see ‘Gizmos’ in the scene view that indicate the spawn locations and area sizes.

Scale – What scale spawned items should have. There are several options here including using the scale directly from the Prefab, using a constant scale, using a multiplier on the prefabs scale and also the option to specify minimum and maximum values within which a random scale will be chosen.

Rotation – What rotation spawned items should have. There are several options here including using the rotation directly from the Prefab, using a constant rotation, and using a random rotation between specified minimum and maximum values.

Events – Lets you hook up call backs or events that should be triggered when spawning starts, loops or completes.

Spawner Events

Start / Loop / Complete Actions – If you have Game Framework installed then these options let you add Actions that should be triggered when spawning starts, loops or completes.

Spawner Actions

Scripting

Accessing Spawner

You will need to get a reference to the Spawner component to work programatically with it. You can do this by calling GetComponent<Spawner>() or adding a public Spawner variable to your component and dragging in a reference to the intended Spawner component.

Starting and Stopping Spawning

There are a number of cases when you will often want to manually start and stop the spawning. One example is to manually start and stop spawners when they are not visable to the user to save on the CPU load. This is often used in combination with setting the Automatically Run property to Never so that the spawner doesn’t start spawning items automatically.

With a reference to the spawner, to start spawning use the following method:

To stop spawning use:

A typical scenario would be to call these methods from different invisible triggers as the user approaches / leaves a spawn point  (Game Framework provides collission actions for just this purpose).

You also have access to the PauseSpawning()  and ResumeSpawning()  methods to pause and resume the spawning cycle.

Manual Spawning

You can manually spawn individual items from a Spawner based upon it’s current configuration using the spawners  SpawnOnce()  method. A typical scenario would be to call this from a trigger (Game Framework provides collission actions for just this purpose).

Further Information

Despawning

Eventually you will be done with spawned items and need to return them to the pool for reuse. Desspawning is the process of removing an item from the scene and placing it back onto a pool for others to use. Pro Pooling has several built in despawning components to despawn on common conditions such as a time limit expiring or a collision occurring. You can also easily add your own despawning code for other requirements.

DespawnAfterCollision

The DespawnAfterCollision component can be added to a pooled gameobject that contains a physics collider and will automatically return the item to the pool when a collision of the given type occurs with a gameobject that has the selected tag.

Despawn Collision

DespawnAfterCollision2D

Similar to DespawnAfterCollision, the DespawnAfterCollision2D component can be added to a pooled gameobject that contains a physics 2D collider and will automatically return the item to the pool when a collision of the given type occurs with a gameobject that has the selected tag.

Despawn Collision2D

DespawnAfterDelay

The DespawnAfterDelay component will automatically return the item to the pool after a given delay.

Despawn Delay

Setup and Usage

Simply add the desired despawn component from under Add Component | Pro Pooling to your pooled prefab and it will automatically be despawned when the condition is met.

Our free Game Framework asset also allows you to setup advanced actions to take when despawning.

Scripting

The despawner components themselves don’t have any special scripting API. For information on despawning from code see the section on using pools under scripting.

Managing Pooled Items LifeCycle

When items are spawned / despawned you might need to reset certain values that were set when an item was previously active. One example would be to reset the RigidBody velocity so that a newly spawned item doesn’t automatically move with the same velocity as the last time it was spawned. There are several PoolItem components that allow for initialising and resetting a number of such common properties. You can easily create new such components using the IPoolComponent interface which is described in further detail in the scripting section.

The following standard lifecycle components are provided:

  • OnSpawnEnableChildren –  will activate all child gameobjects when the parent gameobject is spawned from the pool.
  • OnDespawnResetRigidbody – will reset various physics properties such as velocity when despawned.
  • OnDespawnResetRigidbody2D – will reset various physics 2D properties such as velocity when despawned.
  • OnDespawnResetTransform – will reset the location, rotation and scale when despawned.
  • OnPoolItemLifecycleActions – run Game Framework actions when the item is spawned / despawned (see the working with Game Framework section below).

Lifecycle Components

Further Information

Working With Game Framework

Pro Pooling includes several extensions for use with our free Game Framework asset (Pro Pooling is also included as a part of the Game Framework Extras Bundle along with some of our other assets). These extensions include the ability to run Game Framework Game Actions on Spawn / Despawn events, and also pluggable Game Actions that can be added to things like collision handlers that let you interact with Pro Pooling, such as spawning items.

Run Actions When Items are Spawned / Despawned

The OnPoolItemLifecycleActions component can be added to a pooled prefab and lets you run Game Framework Game Actions when the item is Spawned or Despawned. OnPoolItemLifecycleActions can be used in addition to the other Pool Lifecycle components mentioned above and used for things like spawning additional ‘child’ items, adding a force or playing audio when an item is spawned.

To use just add the component onto your pooled prefab and select and configure the desired actions that should run when the item is spawned and despawned.

 

 

 

 

 

 

Actions

Pro Pooling includes several actions that can be used within components that support Game Actions such as the Game Framework Run Game Actions and Collision Handler components and the Beautiful Transitions transition components. The actions let you do things such as start a spawner when a collision occurs, spawn items such as enemies when a point in a level is reached, or fireworks when a level is won all in a high performant and code free manner.

The provided Game Actions include:

  • Despawn – Despawn the current item back to a pool
  • Pause Spawner – Pause the specified Spawner component
  • Resume Spawner – Resume the specified Spawner component
  • Spawn Burst – Spawn a single burst of items from a pool
  • Spawn – Spawn items from a pool
  • Start Spawner – Start the specified Spawner component
  • Stop Spawner – Stop the specified Spawner component

Further Information

Scripting

Setup

You can do many things in Pro Pooling without ever leaving the editor however scripting opens up even more possabilities.

Please note that to access the Pro Pooling classes you will need to add the following using statements at the top of your c# code files as shown below.

Creating Pools

You can directly create your own pools from code by creating a new instance of Pool using similar parameters to discussed above in the section on Global Pools. You should also call the Pool Fill() method to populate the Pool according to the settings passed to the constructor.

Created pools can be either added to Global Pools to make them available to other components, or used independently. You could for example create a pool in a component’s OnEnable method and destroy it in it’s OnDisable method. You should store the returned reference for further usage.

Using a Pool

With a pool setup, you just need to spawn items from the pool when you want to use then and despawn them back to the pool when you are done. Before touching on the Spawning method it is useful to understand what a PoolItem is. While not essential for basic usage, it can help if you want to expand upon the existing feature set.

PoolItem

Internally Pro Pooling stores each item in the pool as a PoolItem (or you own subclass of this). PoolItem has a reference to the instance of the gameobject and it’s parent pool and handles among other things reference caching and lifecycle interaction with any components on the pooled gameobject that implement the IPoolComponent interface (see below). When spawning / despawning items from / to a pool you can opt to either obtain the PoolItem (which has a reference to the associated gameobject), or work with the gameobject directly. Where possible it is advised to work with the PoolItem as it provides, performance improvements, and short cuts such as the ReturnSelf() method for despawning directly back into a pool without any lookup.

Spawning and Despawning

To get an item from a pool simply call Spawn() (to get a gameobject reference) or SpawnPoolItem() (to get a PoolItem reference). Overloads of these methods allow for specifying the position, rotation and parent gameobject.

To return an item to the pool pass the reference back to Despawn(), or if using a PoolItem call it’s ReturnSelf() method. A common pattern is to create your own components that use these methods so the pool items themselves can handle when to despawn. You can also use the provided despawn components if they meet your requirements.

Life Cycle Events

Under certain conditions you might need your pooled instances to react to various ‘Life Cycle’ events. As we are reusing gameobjects we often need to reset certain properties between each time we use a pooled item. A typical example of this is resetting a RigidBody’s velocity so when an item is reused it doesn’t start moving with its old speed.

Life cycle events are implemented through the IPoolComponent interface:

Implement this interface on any component that is contained in your pooled prefab to automatically have it’s OnSpawn() and OnDespawn() methods called when the corresponding item is spawned from the pool or despawned back. It can be useful to save the poolItem reference passed in OnSpawn within your component so you can easily return the item back to the pool using the polItem.ReturnSelf() method at a later time e.g. within a physics collision handler.

The following standard lifecycle components are provided:

  • OnSpawnEnableChildren –  will activate all child gameobjects when the parent gameobject is spawned from the pool.
  • OnDespawnResetRigidbody – will reset various physics properties such as velocity when despawned.
  • OnDespawnResetRigidbody2D – will reset various physics 2D properties such as velocity when despawned.
  • OnDespawnResetTransform – will reset the location, rotation and scale when despawned.

See the LifeCycleCallback demo or the provided components under FlipWebApps/ProPooling/Scripts/PoolItemComponents for an example of how this works in practice.

Per Pool Item Data (Generics)

Pro Pooling can makes use of generics to let you use your own subclasses of PoolItem so that you can store your own data or handle life cycle events at the pool item level. As an example a pooled prefab might contain several existing components that you need references to (or even just a single reference to a master component that already does this). Rather than calling GetComponent to retrieve these references every time you get the item from the pool, you can create your own PoolItem subclass and do this setup just once by overriding the PoolItem OnSetup() method.

PoolItem has the following lifecycle methods that you can override in your subclass, and you can also then add your own class data as needed:

Creating a pool based upon a custom pool item must be done manually as GlobalPools only works with standard PoolItem types. The PoolGeneric class (or your own subclass) should be used in place of Pool.

And then make use of our custom pool item.

See the CustomPoolItemMetaData demo, the comments on the virtual methods in the PoolItem class and the PoolGeneric class for more information.

Additional Help

Please view the included demo’s under the \FlipWebApps\ProPooling\_Demo folder for examples and source code for implementing common scenarios. You can also refer to the API documentation for details on the Pro Pooling API.

If you need help or support then please visit our support forum, or let us know if you have any suggestions, feature requests or comments. We are always looking to improve our products.

If you like Pro Pooling then please leave us a review on the asset store as it is great to hear how it is being used and encourages us to continue adding new features.