You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
6.4 KiB
228 lines
6.4 KiB
using UnityEngine; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
|
|
// Cartoon FX - (c) 2012-2016 Jean Moreno |
|
|
|
// Spawn System: |
|
// Preload GameObject to reuse them later, avoiding to Instantiate them. |
|
// Very useful for mobile platforms. |
|
|
|
public class CFX_SpawnSystem : MonoBehaviour |
|
{ |
|
/// <summary> |
|
/// Get the next available preloaded Object. |
|
/// </summary> |
|
/// <returns> |
|
/// The next available preloaded Object. |
|
/// </returns> |
|
/// <param name='sourceObj'> |
|
/// The source Object from which to get a preloaded copy. |
|
/// </param> |
|
/// <param name='activateObject'> |
|
/// Activates the object before returning it. |
|
/// </param> |
|
static public GameObject GetNextObject(GameObject sourceObj, bool activateObject = true) |
|
{ |
|
int uniqueId = sourceObj.GetInstanceID(); |
|
|
|
if(!instance.poolCursors.ContainsKey(uniqueId)) |
|
{ |
|
Debug.LogError("[CFX_SpawnSystem.GetNextObject()] Object hasn't been preloaded: " + sourceObj.name + " (ID:" + uniqueId + ")\n", instance); |
|
return null; |
|
} |
|
|
|
int cursor = instance.poolCursors[uniqueId]; |
|
GameObject returnObj = null; |
|
if(instance.onlyGetInactiveObjects) |
|
{ |
|
int loop = cursor; |
|
while(true) |
|
{ |
|
returnObj = instance.instantiatedObjects[uniqueId][cursor]; |
|
instance.increasePoolCursor(uniqueId); |
|
cursor = instance.poolCursors[uniqueId]; |
|
|
|
if(returnObj != null && !returnObj.activeSelf) |
|
break; |
|
|
|
//complete loop: no active instance available |
|
if(cursor == loop) |
|
{ |
|
if(instance.instantiateIfNeeded) |
|
{ |
|
Debug.Log("[CFX_SpawnSystem.GetNextObject()] A new instance has been created for \"" + sourceObj.name + "\" because no active instance were found in the pool.\n", instance); |
|
PreloadObject(sourceObj); |
|
var list = instance.instantiatedObjects[uniqueId]; |
|
returnObj = list[list.Count-1]; |
|
break; |
|
} |
|
else |
|
{ |
|
Debug.LogWarning("[CFX_SpawnSystem.GetNextObject()] There are no active instances available in the pool for \"" + sourceObj.name +"\"\nYou may need to increase the preloaded object count for this prefab?", instance); |
|
return null; |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
returnObj = instance.instantiatedObjects[uniqueId][cursor]; |
|
instance.increasePoolCursor(uniqueId); |
|
} |
|
|
|
if(activateObject && returnObj != null) |
|
returnObj.SetActive(true); |
|
|
|
return returnObj; |
|
} |
|
|
|
/// <summary> |
|
/// Preloads an object a number of times in the pool. |
|
/// </summary> |
|
/// <param name='sourceObj'> |
|
/// The source Object. |
|
/// </param> |
|
/// <param name='poolSize'> |
|
/// The number of times it will be instantiated in the pool (i.e. the max number of same object that would appear simultaneously in your Scene). |
|
/// </param> |
|
static public void PreloadObject(GameObject sourceObj, int poolSize = 1) |
|
{ |
|
instance.addObjectToPool(sourceObj, poolSize); |
|
} |
|
|
|
/// <summary> |
|
/// Unloads all the preloaded objects from a source Object. |
|
/// </summary> |
|
/// <param name='sourceObj'> |
|
/// Source object. |
|
/// </param> |
|
static public void UnloadObjects(GameObject sourceObj) |
|
{ |
|
instance.removeObjectsFromPool(sourceObj); |
|
} |
|
|
|
/// <summary> |
|
/// Gets a value indicating whether all objects defined in the Editor are loaded or not. |
|
/// </summary> |
|
/// <value> |
|
/// <c>true</c> if all objects are loaded; otherwise, <c>false</c>. |
|
/// </value> |
|
static public bool AllObjectsLoaded |
|
{ |
|
get |
|
{ |
|
return instance.allObjectsLoaded; |
|
} |
|
} |
|
|
|
// INTERNAL SYSTEM ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
static private CFX_SpawnSystem instance; |
|
|
|
public GameObject[] objectsToPreload = new GameObject[0]; |
|
public int[] objectsToPreloadTimes = new int[0]; |
|
public bool hideObjectsInHierarchy = false; |
|
public bool spawnAsChildren = true; |
|
public bool onlyGetInactiveObjects = false; |
|
public bool instantiateIfNeeded = false; |
|
|
|
private bool allObjectsLoaded; |
|
private Dictionary<int,List<GameObject>> instantiatedObjects = new Dictionary<int, List<GameObject>>(); |
|
private Dictionary<int,int> poolCursors = new Dictionary<int, int>(); |
|
|
|
private void addObjectToPool(GameObject sourceObject, int number) |
|
{ |
|
int uniqueId = sourceObject.GetInstanceID(); |
|
|
|
//Add new entry if it doesn't exist |
|
if(!instantiatedObjects.ContainsKey(uniqueId)) |
|
{ |
|
instantiatedObjects.Add(uniqueId, new List<GameObject>()); |
|
poolCursors.Add(uniqueId, 0); |
|
} |
|
|
|
//Add the new objects |
|
GameObject newObj; |
|
for(int i = 0; i < number; i++) |
|
{ |
|
newObj = (GameObject)Instantiate(sourceObject); |
|
newObj.SetActive(false); |
|
|
|
//Set flag to not destruct object |
|
CFX_AutoDestructShuriken[] autoDestruct = newObj.GetComponentsInChildren<CFX_AutoDestructShuriken>(true); |
|
foreach(CFX_AutoDestructShuriken ad in autoDestruct) |
|
{ |
|
ad.OnlyDeactivate = true; |
|
} |
|
//Set flag to not destruct light |
|
CFX_LightIntensityFade[] lightIntensity = newObj.GetComponentsInChildren<CFX_LightIntensityFade>(true); |
|
foreach(CFX_LightIntensityFade li in lightIntensity) |
|
{ |
|
li.autodestruct = false; |
|
} |
|
|
|
instantiatedObjects[uniqueId].Add(newObj); |
|
|
|
if(hideObjectsInHierarchy) |
|
newObj.hideFlags = HideFlags.HideInHierarchy; |
|
|
|
if(spawnAsChildren) |
|
newObj.transform.parent = this.transform; |
|
} |
|
} |
|
|
|
private void removeObjectsFromPool(GameObject sourceObject) |
|
{ |
|
int uniqueId = sourceObject.GetInstanceID(); |
|
|
|
if(!instantiatedObjects.ContainsKey(uniqueId)) |
|
{ |
|
Debug.LogWarning("[CFX_SpawnSystem.removeObjectsFromPool()] There aren't any preloaded object for: " + sourceObject.name + " (ID:" + uniqueId + ")\n", this.gameObject); |
|
return; |
|
} |
|
|
|
//Destroy all objects |
|
for(int i = instantiatedObjects[uniqueId].Count - 1; i >= 0; i--) |
|
{ |
|
GameObject obj = instantiatedObjects[uniqueId][i]; |
|
instantiatedObjects[uniqueId].RemoveAt(i); |
|
GameObject.Destroy(obj); |
|
} |
|
|
|
//Remove pool entry |
|
instantiatedObjects.Remove(uniqueId); |
|
poolCursors.Remove(uniqueId); |
|
} |
|
|
|
private void increasePoolCursor(int uniqueId) |
|
{ |
|
instance.poolCursors[uniqueId]++; |
|
if(instance.poolCursors[uniqueId] >= instance.instantiatedObjects[uniqueId].Count) |
|
{ |
|
instance.poolCursors[uniqueId] = 0; |
|
} |
|
} |
|
|
|
//-------------------------------- |
|
|
|
void Awake() |
|
{ |
|
if(instance != null) |
|
Debug.LogWarning("CFX_SpawnSystem: There should only be one instance of CFX_SpawnSystem per Scene!\n", this.gameObject); |
|
|
|
instance = this; |
|
} |
|
|
|
void Start() |
|
{ |
|
allObjectsLoaded = false; |
|
|
|
for(int i = 0; i < objectsToPreload.Length; i++) |
|
{ |
|
PreloadObject(objectsToPreload[i], objectsToPreloadTimes[i]); |
|
} |
|
|
|
allObjectsLoaded = true; |
|
} |
|
}
|
|
|