229 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			229 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | 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; | ||
|  | 	} | ||
|  | } |