Unity 物件池的簡單介紹(Dictionary使用)
阿新 • • 發佈:2019-02-01
使用物件池的目的:增加頻繁使用的遊戲物體的 複用性 (遊戲物體(敵人小兵)反覆的建立與銷燬 會消耗比較多的效能)
建立物件池的步驟:
1.建立一個存放物件的字典(物件池)
2.對物件池的操作方法
2.1建立物件 CreateObject()
2.2為物件池新增元素 Add()
2.3尋找可以使用的物件 FindUseObj()
2.4回收物件 CollectObject()
3.釋放資源 Clear();
實現如下
1.實現一個單例,用於管理程式碼
2.實現物件池using System.Collections; using System.Collections.Generic; using UnityEngine; public class MonoSingleton<T>:MonoBehaviour where T:Component { private static T t; public static T Intance{ get{ t = GameObject.FindObjectOfType(typeof(T)) as T; if(t==null) { GameObject go = new GameObject(); t = go.AddComponent<T>(); go.name = t + "Object"; } //在場景切換時不要銷燬 DontDestroyOnLoad(t); return t; } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 物件(頻發使用的遊戲物體) 子彈 技能 敵人 /// </summary> public class ObjectPool : MonoSingleton<ObjectPool> { //1.欄位 池 例如:橫掃千軍 技能預製件(因為一個技能可能有多個預製件) 技能的複用性 private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>(); int i = 0; //2.方法 //2.1 建立 //工具類 載入資源 字典 名稱 資源 /// <summary> /// 建立顯示物件 /// </summary> /// <returns>The object.</returns> /// <param name="key">物件名稱</param> /// <param name="go">物件的預製件</param> /// <param name="position">物件的新位置</param> /// <param name="quaternion">物件的角度</param> public GameObject CreateObject(string key,GameObject go,Vector3 position,Quaternion quaternion) { //從池中取出可以使用的物件 GameObject tempgo = FindUseObj(key); if(tempgo!=null) { tempgo.transform.position = position; tempgo.transform.rotation = quaternion; } else{ tempgo = Instantiate(go, position, quaternion) as GameObject; print(i++); Add(key,tempgo); } tempgo.SetActive(true); return tempgo; } /// <summary> /// 為物件池新增元素 /// </summary> /// <returns>The add.</returns> /// <param name="key">Key.</param> /// <param name="tempGo">Temp go.</param> public void Add(string key, GameObject tempGo) { //物件池當中如果沒有鍵(新增鍵) if(!cache.ContainsKey(key)) { cache.Add(key,new List<GameObject>()); } //找到相應的值,為這個列表中新增tempGo //List中的Add方法 //物件池中有鍵就直接在其list中新增值 cache[key].Add(tempGo); } /// <summary> /// 尋找可以使用的物件 /// </summary> /// <returns>The use object.</returns> /// <param name="key">鍵</param> public GameObject FindUseObj(string key) { //在池中且未被使用的物件 if(cache.ContainsKey(key)) { //返回找到的第一個可用的物件(沒有返回 null) return cache[key].Find(p=>!p.activeSelf); /*上面(泛型委託Lambda)這句話的意思 *p=cache[key][i] *if(!cache[key][i].activeSelf=!p.activeSelf) * *實現的方法如下 * for(int i;i<cache[key].Count;i++) * { * if(!cache[key][i].activeSelf) * return cache[key][i]; * } */ } return null; } /// <summary> /// 直接回收 /// </summary> /// <param name="go">Go.</param> public void CollectObject(GameObject go) { go.SetActive(false); } /// <summary> /// 延遲迴收 /// </summary> /// <param name="go">Go.</param> /// <param name="delay">Delay.</param> public void CollectObject(GameObject go, float delay) { StartCoroutine(Collect(go,delay)); } private IEnumerator Collect(GameObject go, float delay) { yield return new WaitForSeconds(delay); CollectObject(go); } /// <summary> /// 釋放資源 /// </summary> /// <returns>The clear.</returns> /// <param name="key">Key.</param> public void Clear(string key) { if(cache.ContainsKey(key)) { //Destroy當中所有的物件 for (int i = 0; i < cache[key].Count;i++) { Destroy(cache[key][i]); } //清除鍵當中的所有值 //cache[key].Clear(); //清除這個鍵(鍵值一起清除) cache.Remove(key); } } /// <summary> /// 釋放所有物件池 /// </summary> public void ClearAll() { var list = new List<string>(cache.Keys); for (int i = 0; i < list.Count;i++) { Clear(list[i]); } } }
3.簡單使用物件池
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolTest : MonoBehaviour {
GameObject go;
GameObject item;
// Use this for initialization
void Start () {
//在Resources檔案下載入Cube預製鍵
go = Resources.Load("Cube") as GameObject;
}
// Update is called once per frame
void Update () {
//按下空格建立一個Cube
if(Input.GetKeyDown(KeyCode.Space))
{
item = ObjectPool.Intance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));
}
//按下左鍵執行回收
if(Input.GetMouseButtonDown(0))
{
if (item != null)
{
ObjectPool.Intance.CollectObject(item, 2);
}
}
//按下右鍵執行清除
if(Input.GetMouseButtonDown(1))
{
ObjectPool.Intance.Clear("Object1");
}
}
}