chore: initial commit
This commit is contained in:
642
Assets/Feel/MMTools/Core/MMObjectPool/MMMultipleObjectPooler.cs
Normal file
642
Assets/Feel/MMTools/Core/MMObjectPool/MMMultipleObjectPooler.cs
Normal file
@@ -0,0 +1,642 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using MoreMountains.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
[Serializable]
|
||||
/// <summary>
|
||||
/// Multiple object pooler object.
|
||||
/// </summary>
|
||||
public class MMMultipleObjectPoolerObject
|
||||
{
|
||||
public GameObject GameObjectToPool;
|
||||
public int PoolSize;
|
||||
public bool PoolCanExpand = true;
|
||||
public bool Enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The various methods you can pull objects from the pool with
|
||||
/// </summary>
|
||||
public enum MMPoolingMethods { OriginalOrder, OriginalOrderSequential, RandomBetweenObjects, RandomPoolSizeBased }
|
||||
|
||||
/// <summary>
|
||||
/// This class allows you to have a pool of various objects to pool from.
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Object Pool/MMMultipleObjectPooler")]
|
||||
public class MMMultipleObjectPooler : MMObjectPooler
|
||||
{
|
||||
/// the list of objects to pool
|
||||
[Tooltip("the list of objects to pool")]
|
||||
public List<MMMultipleObjectPoolerObject> Pool;
|
||||
[MMInformation("A MultipleObjectPooler is a reserve of objects, to be used by a Spawner. When asked, it will return an object from the pool (ideally an inactive one) chosen based on the pooling method you've chosen.\n- OriginalOrder will spawn objects in the order you've set them in the inspector (from top to bottom)\n- OriginalOrderSequential will do the same, but will empty each pool before moving to the next object\n- RandomBetweenObjects will pick one object from the pool, at random, but ignoring its pool size, each object has equal chances to get picked\n- PoolSizeBased randomly choses one object from the pool, based on its pool size probability (the larger the pool size, the higher the chances it'll get picked)'...",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
/// the chosen pooling method
|
||||
[Tooltip("the chosen pooling method")]
|
||||
public MMPoolingMethods PoolingMethod = MMPoolingMethods.RandomPoolSizeBased;
|
||||
[MMInformation("If you set CanPoolSameObjectTwice to false, the Pooler will try to prevent the same object from being pooled twice to avoid repetition. This will only affect random pooling methods, not ordered pooling.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
/// whether or not the same object can be pooled twice in a row. If you set CanPoolSameObjectTwice to false, the Pooler will try to prevent the same object from being pooled twice to avoid repetition. This will only affect random pooling methods, not ordered pooling.
|
||||
[Tooltip("whether or not the same object can be pooled twice in a row. If you set CanPoolSameObjectTwice to false, the Pooler will try to prevent the same object from being pooled twice to avoid repetition. This will only affect random pooling methods, not ordered pooling.")]
|
||||
public bool CanPoolSameObjectTwice = true;
|
||||
/// a unique name that should match on all MMMultipleObjectPoolers you want to use together
|
||||
[Tooltip("a unique name that should match on all MMMultipleObjectPoolers you want to use together")]
|
||||
[MMCondition("MutualizeWaitingPools", true)]
|
||||
public string MutualizedPoolName = "";
|
||||
|
||||
/// if CanPoolSameObjectTwice is set to false, this determines up to how many times we'll iterate to try and find a different object
|
||||
[Tooltip("if CanPoolSameObjectTwice is set to false, this determines up to how many times we'll iterate to try and find a different object")]
|
||||
[MMCondition("CanPoolSameObjectTwice", true, true)]
|
||||
public float OverflowAmount = 10f;
|
||||
|
||||
public virtual List<MMMultipleObjectPooler> Owner { get; set; }
|
||||
private void OnDestroy() { Owner?.Remove(this); }
|
||||
|
||||
/// the actual object pool
|
||||
protected GameObject _lastPooledObject;
|
||||
protected int _currentIndex = 0;
|
||||
protected int _currentIndexCounter = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines the name of the object pool.
|
||||
/// </summary>
|
||||
/// <returns>The object pool name.</returns>
|
||||
protected override string DetermineObjectPoolName()
|
||||
{
|
||||
if ((MutualizedPoolName == null) || (MutualizedPoolName == ""))
|
||||
{
|
||||
return ("[MultipleObjectPooler] " + this.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ("[MultipleObjectPooler] " + MutualizedPoolName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the object pool with the amount of objects you specified in the inspector.
|
||||
/// </summary>
|
||||
public override void FillObjectPool()
|
||||
{
|
||||
if ((Pool == null) || (Pool.Count == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we create a waiting pool, if one already exists, no need to fill anything
|
||||
if (!CreateWaitingPool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if there's only one item in the Pool, we force CanPoolSameObjectTwice to true
|
||||
if (Pool.Count <= 1)
|
||||
{
|
||||
CanPoolSameObjectTwice = true;
|
||||
}
|
||||
|
||||
bool stillObjectsToPool;
|
||||
int[] poolSizes;
|
||||
|
||||
// if we're gonna pool in the original inspector order
|
||||
switch (PoolingMethod)
|
||||
{
|
||||
case MMPoolingMethods.OriginalOrder:
|
||||
stillObjectsToPool = true;
|
||||
// we store our poolsizes in a temp array so it doesn't impact the inspector
|
||||
poolSizes = new int[Pool.Count];
|
||||
for (int i = 0; i < Pool.Count; i++)
|
||||
{
|
||||
poolSizes[i] = Pool[i].PoolSize;
|
||||
}
|
||||
|
||||
// we go through our objects in the order they were in the inspector, and fill the pool while we find objects to add
|
||||
while (stillObjectsToPool)
|
||||
{
|
||||
stillObjectsToPool = false;
|
||||
for (int i = 0; i < Pool.Count; i++)
|
||||
{
|
||||
if (poolSizes[i] > 0)
|
||||
{
|
||||
AddOneObjectToThePool(Pool[i].GameObjectToPool);
|
||||
poolSizes[i]--;
|
||||
stillObjectsToPool = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MMPoolingMethods.OriginalOrderSequential:
|
||||
// we store our poolsizes in a temp array so it doesn't impact the inspector
|
||||
foreach (MMMultipleObjectPoolerObject pooledGameObject in Pool)
|
||||
{
|
||||
for (int i = 0; i < pooledGameObject.PoolSize ; i++ )
|
||||
{
|
||||
AddOneObjectToThePool(pooledGameObject.GameObjectToPool);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
int k = 0;
|
||||
// for each type of object specified in the inspector
|
||||
foreach (MMMultipleObjectPoolerObject pooledGameObject in Pool)
|
||||
{
|
||||
// if there's no specified number of objects to pool for that type of object, we do nothing and exit
|
||||
if (k > Pool.Count) { return; }
|
||||
|
||||
// we add, one by one, the number of objects of that type, as specified in the inspector
|
||||
for (int j = 0; j < Pool[k].PoolSize; j++)
|
||||
{
|
||||
AddOneObjectToThePool(pooledGameObject.GameObjectToPool);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds one object of the specified type to the object pool.
|
||||
/// </summary>
|
||||
/// <returns>The object that just got added.</returns>
|
||||
/// <param name="typeOfObject">The type of object to add to the pool.</param>
|
||||
protected virtual GameObject AddOneObjectToThePool(GameObject typeOfObject)
|
||||
{
|
||||
if (typeOfObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
bool initialStatus = typeOfObject.activeSelf;
|
||||
typeOfObject.SetActive(false);
|
||||
GameObject newGameObject = (GameObject)Instantiate(typeOfObject);
|
||||
typeOfObject.SetActive(initialStatus);
|
||||
SceneManager.MoveGameObjectToScene(newGameObject, this.gameObject.scene);
|
||||
if (NestWaitingPool)
|
||||
{
|
||||
newGameObject.transform.SetParent(_waitingPool.transform);
|
||||
}
|
||||
newGameObject.name = typeOfObject.name;
|
||||
_objectPool.PooledGameObjects.Add(newGameObject);
|
||||
return newGameObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random object from the pool.
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object.</returns>
|
||||
public override GameObject GetPooledGameObject()
|
||||
{
|
||||
GameObject pooledGameObject;
|
||||
switch (PoolingMethod)
|
||||
{
|
||||
case MMPoolingMethods.OriginalOrder:
|
||||
pooledGameObject = GetPooledGameObjectOriginalOrder();
|
||||
break;
|
||||
case MMPoolingMethods.RandomPoolSizeBased:
|
||||
pooledGameObject = GetPooledGameObjectPoolSizeBased();
|
||||
break;
|
||||
case MMPoolingMethods.RandomBetweenObjects:
|
||||
pooledGameObject = GetPooledGameObjectRandomBetweenObjects();
|
||||
break;
|
||||
case MMPoolingMethods.OriginalOrderSequential:
|
||||
pooledGameObject = GetPooledGameObjectOriginalOrderSequential();
|
||||
break;
|
||||
default:
|
||||
pooledGameObject = null;
|
||||
break;
|
||||
}
|
||||
if (pooledGameObject!=null)
|
||||
{
|
||||
_lastPooledObject = pooledGameObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastPooledObject = null;
|
||||
}
|
||||
return pooledGameObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find a gameobject in the pool according to the order the list has been setup in (one of each, no matter how big their respective pool sizes)
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object original order.</returns>
|
||||
protected virtual GameObject GetPooledGameObjectOriginalOrder()
|
||||
{
|
||||
int newIndex;
|
||||
// if we've reached the end of our list, we start again from the beginning
|
||||
if (_currentIndex >= Pool.Count)
|
||||
{
|
||||
ResetCurrentIndex ();
|
||||
}
|
||||
|
||||
MMMultipleObjectPoolerObject searchedObject = GetPoolObject(Pool[_currentIndex].GameObjectToPool);
|
||||
|
||||
if (_currentIndex >= _objectPool.PooledGameObjects.Count) { return null; }
|
||||
if (!searchedObject.Enabled) { _currentIndex++; return null; }
|
||||
|
||||
// if the object is already active, we need to find another one
|
||||
if (_objectPool.PooledGameObjects[_currentIndex].gameObject.activeInHierarchy)
|
||||
{
|
||||
GameObject findObject = FindInactiveObject(_objectPool.PooledGameObjects[_currentIndex].gameObject.name,_objectPool.PooledGameObjects);
|
||||
if (findObject != null)
|
||||
{
|
||||
_currentIndex++;
|
||||
return findObject;
|
||||
}
|
||||
|
||||
// if its pool can expand, we create a new one
|
||||
if (searchedObject.PoolCanExpand)
|
||||
{
|
||||
_currentIndex++;
|
||||
return AddOneObjectToThePool(searchedObject.GameObjectToPool);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it can't expand we return nothing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the object is inactive, we return it
|
||||
newIndex = _currentIndex;
|
||||
_currentIndex++;
|
||||
return _objectPool.PooledGameObjects[newIndex];
|
||||
}
|
||||
}
|
||||
|
||||
protected int _currentCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find a gameobject in the pool according to the order the list has been setup in (one of each, no matter how big their respective pool sizes)
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object original order.</returns>
|
||||
protected virtual GameObject GetPooledGameObjectOriginalOrderSequential()
|
||||
{
|
||||
// if we've reached the end of our list, we start again from the beginning
|
||||
if (_currentIndex >= Pool.Count)
|
||||
{
|
||||
_currentCount = 0;
|
||||
ResetCurrentIndex ();
|
||||
}
|
||||
|
||||
MMMultipleObjectPoolerObject searchedObject = GetPoolObject(Pool[_currentIndex].GameObjectToPool);
|
||||
|
||||
if (_currentIndex >= _objectPool.PooledGameObjects.Count) { return null; }
|
||||
if (!searchedObject.Enabled) { _currentIndex++; _currentCount = 0; return null; }
|
||||
|
||||
|
||||
// if the object is already active, we need to find another one
|
||||
if (_objectPool.PooledGameObjects[_currentIndex].gameObject.activeInHierarchy)
|
||||
{
|
||||
GameObject findObject = FindInactiveObject(Pool[_currentIndex].GameObjectToPool.name, _objectPool.PooledGameObjects);
|
||||
if (findObject != null)
|
||||
{
|
||||
_currentCount++;
|
||||
OrderSequentialResetCounter(searchedObject);
|
||||
return findObject;
|
||||
}
|
||||
|
||||
// if its pool can expand, we create a new one
|
||||
if (searchedObject.PoolCanExpand)
|
||||
{
|
||||
_currentCount++;
|
||||
OrderSequentialResetCounter(searchedObject);
|
||||
return AddOneObjectToThePool(searchedObject.GameObjectToPool);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it can't expand we return nothing
|
||||
_currentIndex++;
|
||||
_currentCount = 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the object is inactive, we return it
|
||||
_currentCount++;
|
||||
OrderSequentialResetCounter(searchedObject);
|
||||
return _objectPool.PooledGameObjects[_currentIndex];
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OrderSequentialResetCounter(MMMultipleObjectPoolerObject searchedObject)
|
||||
{
|
||||
if (_currentCount >= searchedObject.PoolSize)
|
||||
{
|
||||
_currentIndex++;
|
||||
_currentCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Randomly choses one object from the pool, based on its pool size probability (the larger the pool size, the higher the chances it'll get picked)
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object pool size based.</returns>
|
||||
protected virtual GameObject GetPooledGameObjectPoolSizeBased()
|
||||
{
|
||||
// we get a random index
|
||||
int randomIndex = UnityEngine.Random.Range(0, _objectPool.PooledGameObjects.Count);
|
||||
|
||||
int overflowCounter=0;
|
||||
|
||||
// we check to see if that object is enabled, if it's not we loop
|
||||
while (!PoolObjectEnabled(_objectPool.PooledGameObjects[randomIndex]) && overflowCounter < _objectPool.PooledGameObjects.Count)
|
||||
{
|
||||
randomIndex = UnityEngine.Random.Range(0, _objectPool.PooledGameObjects.Count);
|
||||
overflowCounter++;
|
||||
}
|
||||
|
||||
if (!PoolObjectEnabled(_objectPool.PooledGameObjects[randomIndex]))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// if we can't pool the same object twice, we'll loop for a while to try and get another one
|
||||
overflowCounter = 0;
|
||||
if (_lastPooledObject != null)
|
||||
{
|
||||
while (!CanPoolSameObjectTwice
|
||||
&& (_objectPool.PooledGameObjects[randomIndex].name == _lastPooledObject.name || !PoolObjectEnabled(_objectPool.PooledGameObjects[randomIndex]))
|
||||
&& overflowCounter < _objectPool.PooledGameObjects.Count * OverflowAmount)
|
||||
{
|
||||
randomIndex = UnityEngine.Random.Range(0, _objectPool.PooledGameObjects.Count);
|
||||
overflowCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
// if the item we've picked is active
|
||||
if (_objectPool.PooledGameObjects[randomIndex].gameObject.activeInHierarchy)
|
||||
{
|
||||
// we try to find another inactive object of the same type
|
||||
GameObject pulledObject = FindInactiveObject(_objectPool.PooledGameObjects[randomIndex].gameObject.name,_objectPool.PooledGameObjects);
|
||||
if (pulledObject!=null)
|
||||
{
|
||||
return pulledObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we couldn't find an inactive object of this type, we see if it can expand
|
||||
MMMultipleObjectPoolerObject searchedObject = GetPoolObject(_objectPool.PooledGameObjects[randomIndex].gameObject);
|
||||
if (searchedObject==null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// if the pool for this object is allowed to grow (this is set in the inspector if you're wondering)
|
||||
if (searchedObject.PoolCanExpand)
|
||||
{
|
||||
return AddOneObjectToThePool(searchedObject.GameObjectToPool);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it's not allowed to grow, we return nothing.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the pool wasn't empty, we return the random object we've found.
|
||||
return _objectPool.PooledGameObjects[randomIndex];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one object from the pool, at random, but ignoring its pool size, each object has equal chances to get picked
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object random between objects.</returns>
|
||||
protected virtual GameObject GetPooledGameObjectRandomBetweenObjects()
|
||||
{
|
||||
// we pick one of the objects in the original pool at random
|
||||
int randomIndex = UnityEngine.Random.Range(0, Pool.Count);
|
||||
|
||||
int overflowCounter=0;
|
||||
|
||||
// if we can't pool the same object twice, we'll loop for a while to try and get another one
|
||||
if (_lastPooledObject != null)
|
||||
{
|
||||
while (!CanPoolSameObjectTwice
|
||||
&& (Pool[randomIndex].GameObjectToPool.name == _lastPooledObject.name || !PoolObjectEnabled(Pool[randomIndex].GameObjectToPool))
|
||||
&& overflowCounter < _objectPool.PooledGameObjects.Count * OverflowAmount)
|
||||
{
|
||||
randomIndex = UnityEngine.Random.Range(0, Pool.Count);
|
||||
overflowCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
int originalRandomIndex = randomIndex+1;
|
||||
|
||||
bool objectFound = false;
|
||||
|
||||
// while we haven't found an object to return, and while we haven't gone through all the different object types, we keep going
|
||||
overflowCounter=0;
|
||||
while (!objectFound
|
||||
&& randomIndex != originalRandomIndex
|
||||
&& overflowCounter < _objectPool.PooledGameObjects.Count)
|
||||
{
|
||||
// if our index is at the end, we reset it
|
||||
if (randomIndex >= Pool.Count)
|
||||
{
|
||||
randomIndex=0;
|
||||
}
|
||||
|
||||
if (!Pool[randomIndex].Enabled)
|
||||
{
|
||||
randomIndex++;
|
||||
overflowCounter++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we try to find an inactive object of that type in the pool
|
||||
GameObject newGameObject = FindInactiveObject(Pool[randomIndex].GameObjectToPool.name, _objectPool.PooledGameObjects);
|
||||
if (newGameObject!=null)
|
||||
{
|
||||
objectFound=true;
|
||||
return newGameObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there's none and if we can expand, we expand
|
||||
if (Pool[randomIndex].PoolCanExpand)
|
||||
{
|
||||
return AddOneObjectToThePool(Pool[randomIndex].GameObjectToPool);
|
||||
}
|
||||
}
|
||||
randomIndex++;
|
||||
overflowCounter++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected string _tempSearchedName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an object of the type at the specified index in the Pool.
|
||||
/// Note that the whole point of this multiple object pooler is to abstract the various pools and handle
|
||||
/// the picking based on the selected mode. If you plan on just picking from different pools yourself,
|
||||
/// consider simply having multiple single object poolers.
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
public virtual GameObject GetPooledGamObjectAtIndex(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= Pool.Count))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
_tempSearchedName = Pool[index].GameObjectToPool.name;
|
||||
return GetPooledGameObjectOfType(_tempSearchedName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an object of the specified name from the pool
|
||||
/// Note that the whole point of this multiple object pooler is to abstract the various pools and handle
|
||||
/// the picking based on the selected mode. If you plan on just picking from different pools yourself,
|
||||
/// consider simply having multiple single object poolers.
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object of type.</returns>
|
||||
/// <param name="type">Type.</param>
|
||||
public virtual GameObject GetPooledGameObjectOfType(string searchedName)
|
||||
{
|
||||
GameObject newObject = FindInactiveObject(searchedName,_objectPool.PooledGameObjects);
|
||||
|
||||
if (newObject!=null)
|
||||
{
|
||||
return newObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we've not returned the object, that means the pool is empty (at least it means it doesn't contain any object of that specific type)
|
||||
// so if the pool is allowed to expand
|
||||
GameObject searchedObject = FindObject(searchedName,_objectPool.PooledGameObjects);
|
||||
if (searchedObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (GetPoolObject(FindObject(searchedName,_objectPool.PooledGameObjects)).PoolCanExpand)
|
||||
{
|
||||
return AddOneObjectToThePool(searchedObject);
|
||||
}
|
||||
}
|
||||
|
||||
// if the pool was empty for that object and not allowed to expand, we return nothing.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an inactive object in the pool based on its name.
|
||||
/// Returns null if no inactive object by that name were found in the pool
|
||||
/// </summary>
|
||||
/// <returns>The inactive object.</returns>
|
||||
/// <param name="searchedName">Searched name.</param>
|
||||
protected virtual GameObject FindInactiveObject(string searchedName, List<GameObject> list)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
// if we find an object inside the pool that matches the asked type
|
||||
if (list[i].name.Equals(searchedName))
|
||||
{
|
||||
// and if that object is inactive right now
|
||||
if (!list[i].gameObject.activeInHierarchy)
|
||||
{
|
||||
// we return it
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual GameObject FindAnyInactiveObject(List<GameObject> list)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
// and if that object is inactive right now
|
||||
if (!list[i].gameObject.activeInHierarchy)
|
||||
{
|
||||
// we return it
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an object in the pool based on its name, active or inactive
|
||||
/// Returns null if there's no object by that name in the pool
|
||||
/// </summary>
|
||||
/// <returns>The object.</returns>
|
||||
/// <param name="searchedName">Searched name.</param>
|
||||
protected virtual GameObject FindObject(string searchedName,List<GameObject> list)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
// if we find an object inside the pool that matches the asked type
|
||||
if (list[i].name.Equals(searchedName))
|
||||
{
|
||||
// and if that object is inactive right now
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns (if it exists) the MultipleObjectPoolerObject from the original Pool based on a GameObject.
|
||||
/// Note that this is name based.
|
||||
/// </summary>
|
||||
/// <returns>The pool object.</returns>
|
||||
/// <param name="testedObject">Tested object.</param>
|
||||
protected virtual MMMultipleObjectPoolerObject GetPoolObject(GameObject testedObject)
|
||||
{
|
||||
if (testedObject==null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int i=0;
|
||||
foreach(MMMultipleObjectPoolerObject poolerObject in Pool)
|
||||
{
|
||||
if (testedObject.name.Equals(poolerObject.GameObjectToPool.name))
|
||||
{
|
||||
return (poolerObject);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual bool PoolObjectEnabled(GameObject testedObject)
|
||||
{
|
||||
MMMultipleObjectPoolerObject searchedObject = GetPoolObject(testedObject);
|
||||
if (searchedObject != null)
|
||||
{
|
||||
return searchedObject.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void EnableObjects(string name,bool newStatus)
|
||||
{
|
||||
foreach(MMMultipleObjectPoolerObject poolerObject in Pool)
|
||||
{
|
||||
if (name.Equals(poolerObject.GameObjectToPool.name))
|
||||
{
|
||||
poolerObject.Enabled = newStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ResetCurrentIndex()
|
||||
{
|
||||
_currentIndex = 0;
|
||||
_currentIndexCounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73098ca8f002adc4f9debdbe47a78c9a
|
||||
timeCreated: 1523900445
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
85
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectBounds.cs
Normal file
85
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectBounds.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
[AddComponentMenu("More Mountains/Tools/Object Bounds/MMObjectBounds")]
|
||||
public class MMObjectBounds : MonoBehaviour
|
||||
{
|
||||
public enum WaysToDetermineBounds { Collider, Collider2D, Renderer, Undefined }
|
||||
|
||||
[Header("Bounds")]
|
||||
public WaysToDetermineBounds BoundsBasedOn;
|
||||
|
||||
|
||||
public virtual Vector3 Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When this component is added we define its bounds.
|
||||
/// </summary>
|
||||
protected virtual void Reset()
|
||||
{
|
||||
DefineBoundsChoice();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to determine automatically what the bounds should be based on.
|
||||
/// In this order, it'll keep the last found of these : Collider2D, Collider or Renderer.
|
||||
/// If none of these is found, it'll be set as Undefined.
|
||||
/// </summary>
|
||||
protected virtual void DefineBoundsChoice()
|
||||
{
|
||||
BoundsBasedOn = WaysToDetermineBounds.Undefined;
|
||||
if (GetComponent<Renderer>()!=null)
|
||||
{
|
||||
BoundsBasedOn = WaysToDetermineBounds.Renderer;
|
||||
}
|
||||
if (GetComponent<Collider>()!=null)
|
||||
{
|
||||
BoundsBasedOn = WaysToDetermineBounds.Collider;
|
||||
}
|
||||
if (GetComponent<Collider2D>()!=null)
|
||||
{
|
||||
BoundsBasedOn = WaysToDetermineBounds.Collider2D;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the bounds of the object, based on what has been defined
|
||||
/// </summary>
|
||||
public virtual Bounds GetBounds()
|
||||
{
|
||||
if (BoundsBasedOn==WaysToDetermineBounds.Renderer)
|
||||
{
|
||||
if (GetComponent<Renderer>()==null)
|
||||
{
|
||||
throw new Exception("The PoolableObject "+gameObject.name+" is set as having Renderer based bounds but no Renderer component can be found.");
|
||||
}
|
||||
return GetComponent<Renderer>().bounds;
|
||||
}
|
||||
|
||||
if (BoundsBasedOn==WaysToDetermineBounds.Collider)
|
||||
{
|
||||
if (GetComponent<Collider>()==null)
|
||||
{
|
||||
throw new Exception("The PoolableObject "+gameObject.name+" is set as having Collider based bounds but no Collider component can be found.");
|
||||
}
|
||||
return GetComponent<Collider>().bounds;
|
||||
}
|
||||
|
||||
if (BoundsBasedOn==WaysToDetermineBounds.Collider2D)
|
||||
{
|
||||
if (GetComponent<Collider2D>()==null)
|
||||
{
|
||||
throw new Exception("The PoolableObject "+gameObject.name+" is set as having Collider2D based bounds but no Collider2D component can be found.");
|
||||
}
|
||||
return GetComponent<Collider2D>().bounds;
|
||||
}
|
||||
|
||||
return new Bounds(Vector3.zero,Vector3.zero);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
13
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectBounds.cs.meta
Normal file
13
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectBounds.cs.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cd26dd47877d80498c4f66f944bdb09
|
||||
timeCreated: 1523900445
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
12
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPool.cs
Normal file
12
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPool.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
public class MMObjectPool : MonoBehaviour
|
||||
{
|
||||
[MMReadOnly]
|
||||
public List<GameObject> PooledGameObjects;
|
||||
}
|
||||
}
|
||||
11
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPool.cs.meta
Normal file
11
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3148d0478f12644438359651f85a7a92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
235
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPooler.cs
Normal file
235
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPooler.cs
Normal file
@@ -0,0 +1,235 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class, meant to be extended depending on the use (simple, multiple object pooler), and used as an interface by the spawners.
|
||||
/// Still handles common stuff like singleton and initialization on start().
|
||||
/// DO NOT add this class to a prefab, nothing would happen. Instead, add SimpleObjectPooler or MultipleObjectPooler.
|
||||
/// </summary>
|
||||
public abstract class MMObjectPooler : MonoBehaviour
|
||||
{
|
||||
/// singleton pattern
|
||||
public static MMObjectPooler Instance;
|
||||
/// if this is true, the pool will try not to create a new waiting pool if it finds one with the same name.
|
||||
public bool MutualizeWaitingPools = false;
|
||||
/// if this is true, all waiting and active objects will be regrouped under an empty game object. Otherwise they'll just be at top level in the hierarchy
|
||||
public bool NestWaitingPool = true;
|
||||
/// if this is true, the waiting pool will be nested under this object
|
||||
[MMCondition("NestWaitingPool", true)]
|
||||
public bool NestUnderThis = false;
|
||||
|
||||
/// this object is just used to group the pooled objects
|
||||
protected GameObject _waitingPool = null;
|
||||
protected MMObjectPool _objectPool;
|
||||
protected const int _initialPoolsListCapacity = 5;
|
||||
protected bool _onSceneLoadedRegistered = false;
|
||||
|
||||
public static List<MMObjectPool> _pools = new List<MMObjectPool>(_initialPoolsListCapacity);
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
protected static void InitializeStatics()
|
||||
{
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a pooler to the static list if needed
|
||||
/// </summary>
|
||||
/// <param name="pool"></param>
|
||||
public static void AddPool(MMObjectPool pool)
|
||||
{
|
||||
if (_pools == null)
|
||||
{
|
||||
_pools = new List<MMObjectPool>(_initialPoolsListCapacity);
|
||||
}
|
||||
if (!_pools.Contains(pool))
|
||||
{
|
||||
_pools.Add(pool);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a pooler from the static list
|
||||
/// </summary>
|
||||
/// <param name="pool"></param>
|
||||
public static void RemovePool(MMObjectPool pool)
|
||||
{
|
||||
_pools?.Remove(pool);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On awake we fill our object pool
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
FillObjectPool();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the waiting pool or tries to reuse one if there's already one available
|
||||
/// </summary>
|
||||
protected virtual bool CreateWaitingPool()
|
||||
{
|
||||
if (!MutualizeWaitingPools)
|
||||
{
|
||||
// we create a container that will hold all the instances we create
|
||||
_waitingPool = new GameObject(DetermineObjectPoolName());
|
||||
SceneManager.MoveGameObjectToScene(_waitingPool, this.gameObject.scene);
|
||||
_objectPool = _waitingPool.AddComponent<MMObjectPool>();
|
||||
_objectPool.PooledGameObjects = new List<GameObject>();
|
||||
ApplyNesting();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MMObjectPool objectPool = ExistingPool(DetermineObjectPoolName());
|
||||
if (objectPool != null)
|
||||
{
|
||||
_objectPool = objectPool;
|
||||
_waitingPool = objectPool.gameObject;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_waitingPool = new GameObject(DetermineObjectPoolName());
|
||||
SceneManager.MoveGameObjectToScene(_waitingPool, this.gameObject.scene);
|
||||
_objectPool = _waitingPool.AddComponent<MMObjectPool>();
|
||||
_objectPool.PooledGameObjects = new List<GameObject>();
|
||||
ApplyNesting();
|
||||
AddPool(_objectPool);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks for an existing pooler for the same object, returns it if found, returns null otherwise
|
||||
/// </summary>
|
||||
/// <param name="objectToPool"></param>
|
||||
/// <returns></returns>
|
||||
public virtual MMObjectPool ExistingPool(string poolName)
|
||||
{
|
||||
if (_pools == null)
|
||||
{
|
||||
_pools = new List<MMObjectPool>(_initialPoolsListCapacity);
|
||||
}
|
||||
if (_pools.Count == 0)
|
||||
{
|
||||
var pools = FindObjectsOfType<MMObjectPool>();
|
||||
if (pools.Length > 0)
|
||||
{
|
||||
_pools.AddRange(pools);
|
||||
}
|
||||
}
|
||||
foreach (MMObjectPool pool in _pools)
|
||||
{
|
||||
if ((pool != null) && (pool.name == poolName)/* && (pool.gameObject.scene == this.gameObject.scene)*/)
|
||||
{
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If needed, nests the waiting pool under this object
|
||||
/// </summary>
|
||||
protected virtual void ApplyNesting()
|
||||
{
|
||||
if (NestWaitingPool && NestUnderThis && (_waitingPool != null))
|
||||
{
|
||||
_waitingPool.transform.SetParent(this.transform);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the name of the object pool.
|
||||
/// </summary>
|
||||
/// <returns>The object pool name.</returns>
|
||||
protected virtual string DetermineObjectPoolName()
|
||||
{
|
||||
return ("[ObjectPooler] " + this.name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to fill the pool with objects
|
||||
/// </summary>
|
||||
public virtual void FillObjectPool()
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to return a gameobject
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object.</returns>
|
||||
public virtual GameObject GetPooledGameObject()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the object pool
|
||||
/// </summary>
|
||||
public virtual void DestroyObjectPool()
|
||||
{
|
||||
if (_waitingPool != null)
|
||||
{
|
||||
Destroy(_waitingPool.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On enable we register to the scene loaded hook
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (!_onSceneLoadedRegistered)
|
||||
{
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnSceneLoaded we recreate
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="loadSceneMode"></param>
|
||||
private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
|
||||
{
|
||||
if (this == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ((_objectPool == null) || (_waitingPool == null))
|
||||
{
|
||||
if (this != null)
|
||||
{
|
||||
FillObjectPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Destroy we remove ourselves from the list of poolers
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
if ((_objectPool != null) && NestUnderThis)
|
||||
{
|
||||
RemovePool(_objectPool);
|
||||
}
|
||||
|
||||
if (_onSceneLoadedRegistered)
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
_onSceneLoadedRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPooler.cs.meta
Normal file
13
Assets/Feel/MMTools/Core/MMObjectPool/MMObjectPooler.cs.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 744b7d0770e56334f9ed2e0561c50cc3
|
||||
timeCreated: 1523900445
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
70
Assets/Feel/MMTools/Core/MMObjectPool/MMPoolableObject.cs
Normal file
70
Assets/Feel/MMTools/Core/MMObjectPool/MMPoolableObject.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Add this class to an object that you expect to pool from an objectPooler.
|
||||
/// Note that these objects can't be destroyed by calling Destroy(), they'll just be set inactive (that's the whole point).
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Object Pool/MMPoolableObject")]
|
||||
public class MMPoolableObject : MMObjectBounds
|
||||
{
|
||||
[Header("Events")]
|
||||
public UnityEvent ExecuteOnEnable;
|
||||
public UnityEvent ExecuteOnDisable;
|
||||
|
||||
public delegate void Events();
|
||||
public event Events OnSpawnComplete;
|
||||
|
||||
[Header("Poolable Object")]
|
||||
/// The life time, in seconds, of the object. If set to 0 it'll live forever, if set to any positive value it'll be set inactive after that time.
|
||||
public float LifeTime = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Turns the instance inactive, in order to eventually reuse it.
|
||||
/// </summary>
|
||||
public virtual void Destroy()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called every frame
|
||||
/// </summary>
|
||||
protected virtual void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the objects get enabled (usually after having been pooled from an ObjectPooler, we initiate its death countdown.
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
Size = GetBounds().extents * 2;
|
||||
if (LifeTime > 0f)
|
||||
{
|
||||
Invoke("Destroy", LifeTime);
|
||||
}
|
||||
ExecuteOnEnable?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the object gets disabled (maybe it got out of bounds), we cancel its programmed death
|
||||
/// </summary>
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
ExecuteOnDisable?.Invoke();
|
||||
CancelInvoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the on spawn complete event
|
||||
/// </summary>
|
||||
public virtual void TriggerOnSpawnComplete()
|
||||
{
|
||||
OnSpawnComplete?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72de0b0360096ea41a18d17864ecb963
|
||||
timeCreated: 1523900445
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
117
Assets/Feel/MMTools/Core/MMObjectPool/MMSimpleObjectPooler.cs
Normal file
117
Assets/Feel/MMTools/Core/MMObjectPool/MMSimpleObjectPooler.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple object pool outputting a single type of objects
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Object Pool/MMSimpleObjectPooler")]
|
||||
public class MMSimpleObjectPooler : MMObjectPooler
|
||||
{
|
||||
/// the game object we'll instantiate
|
||||
public GameObject GameObjectToPool;
|
||||
/// the number of objects we'll add to the pool
|
||||
public int PoolSize = 20;
|
||||
/// if true, the pool will automatically add objects to the itself if needed
|
||||
public bool PoolCanExpand = true;
|
||||
|
||||
public virtual List<MMSimpleObjectPooler> Owner { get; set; }
|
||||
private void OnDestroy() { Owner?.Remove(this); }
|
||||
|
||||
/// <summary>
|
||||
/// Fills the object pool with the gameobject type you've specified in the inspector
|
||||
/// </summary>
|
||||
public override void FillObjectPool()
|
||||
{
|
||||
if (GameObjectToPool == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if we've already created a pool, we exit
|
||||
if ((_objectPool != null) && (_objectPool.PooledGameObjects.Count > PoolSize))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateWaitingPool ();
|
||||
|
||||
int objectsToSpawn = PoolSize;
|
||||
|
||||
if (_objectPool != null)
|
||||
{
|
||||
objectsToSpawn -= _objectPool.PooledGameObjects.Count;
|
||||
}
|
||||
|
||||
// we add to the pool the specified number of objects
|
||||
for (int i = 0; i < objectsToSpawn; i++)
|
||||
{
|
||||
AddOneObjectToThePool ();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the name of the object pool.
|
||||
/// </summary>
|
||||
/// <returns>The object pool name.</returns>
|
||||
protected override string DetermineObjectPoolName()
|
||||
{
|
||||
return ("[SimpleObjectPooler] " + GameObjectToPool.name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns one inactive object from the pool
|
||||
/// </summary>
|
||||
/// <returns>The pooled game object.</returns>
|
||||
public override GameObject GetPooledGameObject()
|
||||
{
|
||||
// we go through the pool looking for an inactive object
|
||||
for (int i=0; i< _objectPool.PooledGameObjects.Count; i++)
|
||||
{
|
||||
if (!_objectPool.PooledGameObjects[i].gameObject.activeInHierarchy)
|
||||
{
|
||||
// if we find one, we return it
|
||||
return _objectPool.PooledGameObjects[i];
|
||||
}
|
||||
}
|
||||
// if we haven't found an inactive object (the pool is empty), and if we can extend it, we add one new object to the pool, and return it
|
||||
if (PoolCanExpand)
|
||||
{
|
||||
return AddOneObjectToThePool();
|
||||
}
|
||||
// if the pool is empty and can't grow, we return nothing.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds one object of the specified type (in the inspector) to the pool.
|
||||
/// </summary>
|
||||
/// <returns>The one object to the pool.</returns>
|
||||
protected virtual GameObject AddOneObjectToThePool()
|
||||
{
|
||||
if (GameObjectToPool == null)
|
||||
{
|
||||
Debug.LogWarning("The "+gameObject.name+" ObjectPooler doesn't have any GameObjectToPool defined.", gameObject);
|
||||
return null;
|
||||
}
|
||||
|
||||
bool initialStatus = GameObjectToPool.activeSelf;
|
||||
GameObjectToPool.SetActive(false);
|
||||
GameObject newGameObject = (GameObject)Instantiate(GameObjectToPool);
|
||||
GameObjectToPool.SetActive(initialStatus);
|
||||
SceneManager.MoveGameObjectToScene(newGameObject, this.gameObject.scene);
|
||||
if (NestWaitingPool)
|
||||
{
|
||||
newGameObject.transform.SetParent(_waitingPool.transform);
|
||||
}
|
||||
newGameObject.name = GameObjectToPool.name + "-" + _objectPool.PooledGameObjects.Count;
|
||||
|
||||
_objectPool.PooledGameObjects.Add(newGameObject);
|
||||
|
||||
return newGameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b7277539b95c0d45895792ecc99ce66
|
||||
timeCreated: 1523900445
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user