XPool - Object Pooling System for Unity
Created by Hiroya Aramaki (Makihiro)
What is XPool ?
XPool is an object pooling library for Unity.
This was developed to be able to do all the pooling expected in application development with just this library.
- All your classes can be pooled.
- Short code, easy to use.
- Fast performance
- Scalability
- Tested. It works stably.
Table of Contents
📥 Installation
Download any version from releases.
Releases: https://github.com/mackysoft/XPool/releases
Install via PackageManager
Or, you can add this package by opening PackageManager and entering
https://github.com/mackysoft/XPool.git?path=Assets/MackySoft/MackySoft.XPool
from the Add package from git URL
option.
Install via Open UPM
Or, you can install this package from the Open UPM registry.
More details here.
openupm add com.mackysoft.xpool
🔰 Usage
The full Scripting API is here.
Scripting API: https://mackysoft.github.io/XPool/api/MackySoft.XPool.html
Unity Object Pool (GameObject, Component)
Pooling of Unity Object (GameObject, Component) can be performed using GameObjectPool
or ComponentPool<T>
.
These hierarchical objects can be rented by writing them in a similar way to Instantiate
method.
// Example code is being written...
ParticleSystem Pool
Optimized pools are available for some of the components implemented in Unity.
This is an example of ParticleSystemPool
usage.
public class HitParticleSystemEmitter : MonoBehaviour {
[SerializeField]
ParticleSystemPool m_HitParticleSystemPool = new ParticleSystemPool();
void OnCollisionEnter (Collision collision) {
// The rented ParticleSystem is automatically returned to the pool when completed.
m_HitParticleSystemPool.Rent(collision.contacts[0],Quaternion.identity);
}
}
If you need an optimized pool for other components, please refer to the How to write custom pool ? section, or give me feedback via issues or pull requests.
Object Pool (Pure C# Object)
FactoryPool<T>
can be used to pool Pure C# Object.
Unity Object are not supported, as they behave differently from Pure C# Object in that they can be set to null externally with
Destroy
method.
// Give the capacity and factory method to the constructor.
var pool = new FactoryPool<MyClass>(8,() => new MyClass());
// Create new instance by factory if pool is empty.
MyClass instance = pool.Rent();
// Return instance to the pool.
pool.Return(instance);
Collection Pool (T[]
, List<T>
, Qeueue<T>
, Stack<T>
, HashSet<T>
, Dictionary<TKey,TValue>
)
An optimized pool is provided for the generic collections provided in .NET Framework.
// Rent an array from the pool.
// Note that the array length to be rented is the next two powers of minimumLength.
T[] array = ArrayPool<T>.Shared.Rent(minimumLength: 10);
// Return array to the pool.
ArrayPool<T>.Shared.Return(array);
// ListPool<T>, QueuePool<T>, StackPool<T>, HashSetPool<T>, DictionaryPool<TKey,TValue> are also available.
List<T> list = ListPool<T>.Shared.Rent();
Queue<T> queue = QueuePool<T>.Shared.Rent();
Stack<T> stack = StackPool<T>.Shared.Rent();
HashSet<T> hashSet = HashSetPool<T>.Shared.Rent();
Dictionary<TKey,TValue> dictionary = DictionaryPool<TKey,TValue>.Shared.Rent();
Non allocated collections
You can use the TemporaryCollections API that leverages ArrayPool<T>
.
These collections are a struct and internally use array rented from ArrayPool<T>
.
Therefore, it is fast and non-allocation.
// Create a temporary array.
var array = TemporaryArray<T>.Create(10);
// You must release collection when you are done using it.
array.Dispose();
// TemporaryList<T>, TemporaryQueue<T>, TemporaryStack<T> are also available.
TemporaryList<T> list = TemporaryList<T>.Create();
TemporaryQueue<T> queue = TemporaryQueue<T>.Create();
TemporaryStack<T> stack = TemporaryStack<T>.Create();
How to write custom pool ?
If you want to implement a more customized pool, you can quickly create one by using the provided base classes.
The base class of the pool is in the ObjectModel
namespace.
MackySoft.XPool.ObjectMode.PoolBase<T>
MackySoft.XPool.Unity.ObjectModel.UnityObjectPoolBase<T>
MackySoft.XPool.Unity.ObjectModel.ComponentPoolBase<T>
using MackySoft.XPool.ObjectModel; // PoolBase<T> is here.
public class MyPool : PoolBase<MyClass> {
public MyPool () {
}
public MyPool (MyClass original,int capacity) : base(original,capacity) {
}
// Called when Rent is invoked and there are no instances in the pool.
protected override MyClass Factory () {
return new MyClass();
}
// Called when an instance is rented from the pool.
// This is also the case when a new instance is created by the Factory.
protected override void OnRent (MyClass instance) {
}
// Called when an instance is returned to the pool.
protected override void OnReturn (MyClass instance) {
}
// Called when the capacity is exceeded and the instance cannot be returned to the pool,
// or when the instance is released by the ReleaseInstances method.
protected override void OnRelease (MyClass instance) {
}
}
ParticleSystemPool implementation
As an example, ParticleSystemPool
is implemented using ComponentPoolBase<T>
.
Its functionality has been optimized for ParticleSystem.
using System;
using UnityEngine;
using MackySoft.XPool.Unity.ObjectModel; // ComponentPoolBase<T> is here.
[Serializable]
public class ParticleSystemPool : ComponentPoolBase<ParticleSystem> {
[SerializeField]
bool m_PlayOnRent;
public bool PlayOnRent { get => m_PlayOnRent; set => m_PlayOnRent = value; }
public ParticleSystemPool () {
}
public ParticleSystemPool (ParticleSystem original,int capacity) : base(original,capacity) {
}
protected override void OnCreate (ParticleSystem instance) {
var main = instance.main;
main.stopAction = ParticleSystemStopAction.Callback;
var trigger = instance.gameObject.AddComponent<ParticleSystemStoppedTrigger>();
trigger.Initialize(instance,this);
}
protected override void OnRent (ParticleSystem instance) {
if (m_PlayOnRent) {
instance.Play(true);
}
}
protected override void OnReturn (ParticleSystem instance) {
instance.Stop(true,ParticleSystemStopBehavior.StopEmitting);
}
protected override void OnRelease (ParticleSystem instance) {
UnityEngine.Object.Destroy(instance.gameObject);
}
public class ParticleSystemStoppedTrigger : MonoBehaviour {
ParticleSystem m_ParticleSystem;
IPool<ParticleSystem> m_Pool;
internal void Initialize (ParticleSystem ps,IPool<ParticleSystem> pool) {
m_ParticleSystem = ps;
m_Pool = pool;
}
void OnParticleSystemStopped () {
m_Pool?.Return(m_ParticleSystem);
}
}
}
✉ Help & Contribute
I welcome feature requests and bug reports in issues and pull requests.
If you feel that my works are worthwhile, I would greatly appreciate it if you could sponsor me.
GitHub Sponsors: https://github.com/sponsors/mackysoft
📔 Author Info
Hiroya Aramaki is a indie game developer in Japan.
- Twitter: https://twitter.com/makihiro_dev
- Blog: https://mackysoft.net/blog
📜 License
This library is under the MIT License.