? ? ? ?本次介紹兩個腳本GameObjectPool游戲對象池類和MonoSingLeton單例模式類利虫。
? ? ? ?在Unity中不論是在游戲中或者是別的應用場景,我們有時候會需要重復產生相同的物體并銷毀掉冈爹,例如子彈就得不斷生成不斷銷毀倾鲫。但這樣是很消耗性能的崖堤。所以有的大佬就設計了游戲對象池這個概念毅糟。
? ? ? ?游戲對象池腳本掛在一個空物體上,玩家在Unity中不需要使用 Instantiate() 方法進行創(chuàng)建物體弛饭。而是用我GameObjectPool腳本中的CreateObject(string key,GameObject go,Vector3 pos,Quaternion rat)進行創(chuàng)建冕末。依次是預制件名稱、預制件對象侣颂、三維坐標數據档桃、旋轉數據。當使用這個方法創(chuàng)建時物體時憔晒,該物體會成為對象池的子物體藻肄,而當需要到銷毀時對象池會將該物體隱藏,若再次需要用到拒担,則重新設置物體的坐標和旋轉并啟用嘹屯。若對象池內的物體不夠用了才會重新生成一個對象。
? ? ? ?游戲對象池在游戲中只能有一個从撼,所以需要將他設計為單例模式州弟。只需要讓游戲對象池繼承他便可。然后調用他的instance方法就可以了低零。
————————————————————————————————————————
MonoSingLeton腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 單例模式掛載腳本
/// </summary>
public abstract class MonoSingLeton<T> : MonoBehaviour where T : MonoSingLeton<T>
{
? ? private static T m_Instance = null;
? ? //3.
? ? //設計階段婆翔,寫腳本沒有掛在物體上,希望腳本單例模式
? ? //運行時掏婶,需要這個腳本唯一實例啃奴,第1次,調用instance
? ? public static T instance
? ? {
? ? ? ? get
? ? ? ? {
? ? ? ? ? ? if(m_Instance == null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? m_Instance = FindObjectOfType(typeof(T)) as T;
? ? ? ? ? ? ? ? if (m_Instance == null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? m_Instance = new GameObject("Singleton of" + typeof(T).ToString(), typeof(T)).GetComponent<T>();
? ? ? ? ? ? ? ? ? ? m_Instance.Init();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return m_Instance;
? ? ? ? }
? ? }
? ? private void Awake()
? ? {
? ? ? ? if (m_Instance == null)
? ? ? ? {
? ? ? ? ? ? m_Instance = this as T;
? ? ? ? }
? ? }
? ? //提供初始化一種選擇
? ? public virtual void Init() { }
? ? //當程序退出時做清理工作雄妥,單例模式對象=null
? ? private void OnApplicationQuit()
? ? {
? ? ? ? m_Instance = null;
? ? }
}
——————————————————————————————————————
游戲對象池腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 游戲對象池
/// </summary>
public class GameObjectPool : MonoSingLeton<GameObjectPool>
{
? ? //1.創(chuàng)建池
? ? private GameObjectPool()
? ? {
? ? }
? ? //static private GameObjectPool obj = new GameObjectPool();
? ? ////提供得到對象的唯一通道
? ? //static public GameObjectPool GetObject()
? ? //{
? ? //? ? return obj;
? ? //}
? ? private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>();
? ? //2.創(chuàng)建一個對象并使用對象
? ? public GameObject CreateObject(string key,GameObject go,Vector3 pos,Quaternion rat)
? ? {
? ? ? ? //1.查找池中有無可用的游戲對象
? ? ? ? GameObject tempGo = FindUsable(key);
? ? ? ? //2.池中有從池中返回
? ? ? ? if (tempGo != null)
? ? ? ? {
? ? ? ? ? ? tempGo.transform.position = pos;
? ? ? ? ? ? tempGo.transform.rotation = rat;
? ? ? ? ? ? tempGo.SetActive(true);? //表示當前正在使用
? ? ? ? }
? ? ? ? else//3.池中沒有加載最蕾,放入池中再返回
? ? ? ? {
? ? ? ? ? ? tempGo = Instantiate(go, pos, rat) as GameObject;
? ? ? ? ? ? //放入池中
? ? ? ? ? ? Add(key, tempGo);
? ? ? ? }
? ? ? ? tempGo.transform.parent = transform;
? ? ? ? return tempGo;
? ? }
? ? private GameObject FindUsable(string key)
? ? {
? ? ? ? if (cache.ContainsKey(key))
? ? ? ? {
? ? ? ? ? ? //從列表中找出未激活的游戲物體
? ? ? ? ? ? return cache[key].Find((p) => !p.activeSelf);
? ? ? ? }
? ? ? ? return null;
? ? }
? ? private void Add(string key,GameObject go)
? ? {
? ? ? ? //檢查池中有沒有需要的key,沒有的話則創(chuàng)建對應列表
? ? ? ? if (!cache.ContainsKey(key))
? ? ? ? {
? ? ? ? ? ? cache.Add(key,new List<GameObject>());
? ? ? ? }
? ? ? ? cache[key].Add(go);
? ? }
? ? //3.? 釋放資源:從池中刪除對象
? ? //3.1 釋放部分:按key釋放
? ? public void Clear(string key)
? ? {
? ? ? ? if (cache.ContainsKey(key))
? ? ? ? {
? ? ? ? ? ? //銷毀場景中游戲物體
? ? ? ? ? ? for (int i = 0; i < cache[key].Count; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Destroy(cache[key][i]);
? ? ? ? ? ? }
? ? ? ? ? ? //緊緊移除了字典中對象地址
? ? ? ? ? ? cache.Remove(key);
? ? ? ? }
? ? }
? ? //3.2 釋放全部
? ? public void ClearAll()
? ? {
? ? ? ? List<string> list = new List<string>(cache.Keys);
? ? ? ? for (int i = 0; i < list.Count; i++)
? ? ? ? {
? ? ? ? ? ? Clear(list[i]);
? ? ? ? }
? ? }
? ? //4.? 回收對象【從畫面中消失】
? ? //4.1 即使回收對象
? ? public void CollectObject(GameObject go)
? ? {
? ? ? ? go.SetActive(false);
? ? }
? ? //4.2 延時回收對象? 協程
? ? public void CollectObject(GameObject go,float delay)
? ? {
? ? ? ? StartCoroutine(CollectDelay(go,delay));
? ? }
? ? private IEnumerator CollectDelay(GameObject go,float delay)
? ? {
? ? ? ? yield return new WaitForSeconds(delay);
? ? ? ? CollectObject(go);
? ? }
}