Comment on page
Leveraging object pooling
Network entities need to be created and removed all the time. This can be due to entities getting in and out of a LiveQuery, or simply because gameplay requires so. If that is the case, we can leverage coherence's object pooling system in order to avoid costly calls to
Destroy, which are famously expensive operations in Unity.
In this project we use pooling for one very clear use case: the tree logs that get spawned when chopping down a tree.
A player just chopped a tree, and a log has been spawned
This was a natural choice as players will be chopping trees all the time, but we can also assume that they will burn the logs on the fire almost as often. So by pre-allocating a pool of around 10 logs, we should be covered in most cases.
To set up the log to behave like this, all we did was to set that option on the log's own
Check the Log prefab in
The Log Prefab is set to instantiate from a pool
A pool configured like this means that coherence will pre-spawn 10 instances of the Prefab at the beginning of the game.
However if we were to need more, we could request more instances and they would be created and added to the pool. The game can even go above 20. If that were to happen, any instance released beyond 20 wouldn't just be returned to the pool, but would be destroyed.
In other words, 10 and 20 represent the lower and upper limit for the amount of memory we are reserving for the logs alone in our game. We are considering anything above 20 as a temporary exception.
When we press Play, coherence instantiates these 10 logs, deactivate them, and put the pool in the DontDestroyOnLoad scene:
The object pool for logs, ready to use
Because they are inactive, their
CoherenceSynccomponents are not syncing any value.
To spawn a new log we only need to call one line of code. However, we don't provide a reference to a regular Prefab like we would with
Instantiate. We instead leverage the
CoherenceSyncConfigobject that represents the log.
The ChopTree script referencing the log's CoherenceSyncConfig
CoherenceSyncConfigcontains all the info that coherence needs to handle this particular Prefab over the network. If we inspect it, we will notice that it contains in fact how the object is loaded (Load via) and how it's instantiated (Instantiate via).
The Log's CoherenceSyncConfig
You can notice how this is the same info we saw while configuring the
This Sync Config can be found in the
coherence/folder, and is a sub-object of another ScriptableObject: the
Now that we have a reference to it, we can spawn the log with one line of code. In the
ChoppableTreescript, we do something like:
CoherenceSync newLog =
logSyncConfig.GetInstance(transform.position + [...], Quaternion.identity);
This line looks remarkably similar to Unity's own
Instantiatein its syntax. The difference is that it gives us back a reference to the
CoherenceSyncattached to the log instance that will be enabled. From this, we can do all sorts of setup operations by just fetching other components with
GetComponent, to prepare the instance.
When we are done with it (in this case, when it's thrown into the campfire), we can dispose of it:
(this line is in the
Burnable.csclass, inside the
The instance is then automatically returned into the pool, and disabled.
When taking an instance out of the pool or when returning it, coherence doesn't automatically do any particular clean up to its state.
As such, when we reuse a pool instance, it is good practice to think of what values should be reset that might have been messed up by previous usage. We should think about what happens during gameplay, and use
OnDisableas needed to ensure that disabled instances are put in a state that makes them ready to be used again.
For this project, since an object can be burned while being carried, we do some cleaning in the
Grabbable.csclass to prepare the wood logs for another round, like so:
private void OnDisable()
isBeingCarried = false;
_rigidbody.isKinematic = false;
_collider.enabled = true;
// ... in addition to removing any listener set in OnEnable