Hi:
I was wondering how to make a Object Pool List with different GameObjects in it. I watched the live stream video on Unity website, and it is great. My problem is that it only used pooling for 1 type of gameobject in the list. He did mention something about polymorphism, but I am unable to find any tutorials about this kind of pooling method and was wondering if anyone else would know where to find a good tutorial or explanation on this topic.
Thank You: James
Hi,
You can find this useful.
To use this class anywhere in your code just type “PoolingManager.InstantiatePooled( prefab , pos , rot );” or replace “Instantiate”/“Object.Instantiate” from your existing codebase with “PoolingManager.InstantiatePooled” and it should work in most cases I think. Just remember that pooled prefabs need to be disabled after some time and not destroyed (see bottom of this post for more on that).
PoolingManager.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PoolingManager : MonoBehaviour {
///////////////////////////////////////////////////////////////////////////////////////////////
#region FIELDS_&_PROPERTIES
static private PoolingManager _singleton = null;
static private PoolingManager singleton {
get {
if( _singleton==null ) {
InstantiateSingleton();
}
return _singleton;
}
}
private Dictionary<int, Queue<GameObject>> pool = new Dictionary<int, Queue<GameObject>>();
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////
#region MONOBEHAVIOUR_EVENTS
// <summary> Awake </summary>
void Awake () {
if( _singleton==null ) {
_singleton = this;
}
else if( _singleton!=this ) {
Destroy( this );
}
}
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////
#region PRIVATE_FUNCTIONS
/// <summary> Adds new prefab instance to pool. </summary>
private void AddInstanceToPool ( GameObject argPrefab ) {
int instanceID = argPrefab.GetInstanceID();
argPrefab.SetActive( false );
GameObject instance = Instantiate( argPrefab );
argPrefab.SetActive( true );
instance.name = argPrefab.name;
instance.transform.parent = transform;
if( pool.ContainsKey( instanceID )==false ) {
pool.Add( instanceID , new Queue<GameObject>() );
}
pool[instanceID].Enqueue( instance );
}
/// <summary> Gets pooled instance. </summary>
private GameObject GetPooledInstance ( GameObject argPrefab , Vector3 argPosition , Quaternion argRotation ) {
int instanceID = argPrefab.GetInstanceID();
GameObject instance = null;
if( pool.ContainsKey( instanceID ) && pool[instanceID].Count!=0 ) {
if( pool[instanceID].Peek().activeSelf==false ) {
instance = pool[instanceID].Dequeue();
pool[instanceID].Enqueue( instance );
}
else {
AddInstanceToPool( argPrefab );
instance = pool[instanceID].Dequeue();
pool[instanceID].Enqueue( instance );
}
}
else {
AddInstanceToPool( argPrefab );
instance = pool[instanceID].Dequeue();
pool[instanceID].Enqueue( instance );
}
instance.transform.position = argPosition;
instance.transform.rotation = argRotation;
instance.SetActive( true );
return instance;
}
// <summary> Instantiate Singleton </summary>
static private void InstantiateSingleton () {
new GameObject( "#PoolingManager" , typeof(PoolingManager) );
}
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////
#region PUBLIC_STATIC_FUNCTIONS
/// <summary> Instantiates using pooling system </summary>
static public void InstantiatePooled ( GameObject argPrefab , Vector3 argPosition , Quaternion argRotation ) {
singleton.GetPooledInstance( argPrefab , argPosition , argRotation );
}
static public void InstantiatePooled <T> ( GameObject argPrefab , Vector3 argPosition , Quaternion argRotation , System.Action<T> argAction ) {
GameObject instance = singleton.GetPooledInstance( argPrefab , argPosition , argRotation );
T[] tComponents = instance.GetComponentsInChildren<T>();
for( int i = 0 ; i<tComponents.Length ; i++ ) {
argAction( tComponents *);
}
}
static public void InstantiatePooled ( GameObject argPrefab , Vector3 argPosition , Quaternion argRotation , Transform argParentTo ) {
GameObject instance = singleton.GetPooledInstance( argPrefab , argPosition , argRotation );
#if UNITY_EDITOR || DEBUG
if( instance.GetComponent<Rigidbody>()!=null && argParentTo.GetComponent<Rigidbody>()!=null ) {
Debug.LogWarning( "Avoid parenting rigidbodies to another rigidbody. This will causes problems. Ie.: "+instance.name+".transform.SetParent("+argParentTo.name+".transform)" );
Debug.Break();
return;
}
#endif
instance.transform.SetParent( argParentTo , true );
}
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////
}
Important: Pooling will work only if instantiated objects are not destroyed but disabled after some time. So make sure no script is destroying them and every prefab contains simple disable-self-after-delay type of component. Similar to this one for example:
DisableAfterDelay.cs
using UnityEngine;
using System.Collections;
public class DisableAfterDelay : MonoBehaviour {
[SerializeField] private float delay = 2f;
private void OnEnable () {
StartCoroutine( Execute () );
}
private IEnumerator Execute () {
yield return new WaitForSeconds( delay );
gameObject.SetActive( false );
}
}
I think you should make your own custom class and put all different GameObjects in it and make class serializable if required .Now use your custom class to make the Object Pool List for this.