Unity——對象池

前言

     游戲中骡湖,經(jīng)常會大量頻繁的創(chuàng)建、銷毀游戲?qū)ο螅ㄗ訌棥R血粒子特效等)咐旧,這會帶來一定的性能開銷,此時绩蜻,我們可以利用對象池技術(shù)來優(yōu)化.

實現(xiàn)對象池的步驟

    1. 首先铣墨,使用一個數(shù)據(jù)結(jié)構(gòu)直接存儲對象,為了降低裝箱办绝、拆箱操作伊约,使用List<GameObject>來存儲姚淆。
    2. 其次,使用字典Dictionary<string,List<GameObject>>來存儲多個對象屡律。
    3. 然后腌逢,從對象池中提取對象,如果對象池中已經(jīng)存在超埋,則激活該對象搏讶,并且從List集合中移除,否則霍殴,創(chuàng)建新的對象(OutPool方法實現(xiàn)該功能)媒惕。
    4. 最后,將不用的對象再加入到對象池繁成,加入之前吓笙,先判斷該對象對應(yīng)的鍵是否已經(jīng)存在,如果存在巾腕,就直接添加進(jìn)對應(yīng)鍵的值中面睛,否則,創(chuàng)建新的鍵值對尊搬。(JoinPool方法實現(xiàn)該功能)

代碼

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// 對象池單例類
/// </summary>
public class ObjectPoolSingleton
{
    //存儲多個對象(存儲一個也可以哦)
    //使用字典存儲對象名與對象
    //1叁鉴、鍵用的字符串,保存對象的名字佛寿,可以通過名字來從Resources文件夾動態(tài)加載資源
    //2幌墓、用泛型集合直接存儲對象,降低裝箱冀泻、拆箱次數(shù)
    private Dictionary<string, List<GameObject>> pools;
    #region 單例
    private static ObjectPoolSingleton instance;
    private ObjectPoolSingleton()
    {
        //初始化對象池        
        pools = new Dictionary<string, List<GameObject>>();
    }
  
    public static ObjectPoolSingleton Instance
    {
        get { return instance = instance ?? new ObjectPoolSingleton(); }
    }
    #endregion
    /// <summary>
    /// 出對象池(激活對象)
    /// </summary>
    /// <param name="objName">對象的名稱</param>
    /// <param name="pos">位置</param>
    /// <param name="qua">旋轉(zhuǎn)</param>
    /// <returns></returns>
    public GameObject OutPool(string objName, Vector3 pos, Quaternion qua)
    {
        //首先根據(jù)名稱判斷字典里有沒有該對象
        if (pools.ContainsKey(objName))
        {
            //有,再判斷個數(shù)(想想常侣,為什么要判斷個數(shù),難道還會為0弹渔?)
            if (pools[objName].Count > 0)
            {
                //獲得第集合第一個對象
                GameObject currentObj = pools[objName][0];
                //提取了胳施,就應(yīng)該將其從集合中移除
                pools[objName].Remove(currentObj);
                //激活該對象
                currentObj.SetActive(true);
                //初始化該對象的位置、旋轉(zhuǎn)信息
                currentObj.transform.position = pos;
                currentObj.transform.rotation = qua;
                return currentObj;
            }           
        }
        //沒有肢专,怎么辦呢舞肆,創(chuàng)建一個,我們這里是用Resources動態(tài)加載要實例化的對象
        GameObject newObj = GameObject.Instantiate(Resources.Load<GameObject>(objName), pos, qua) as GameObject;
        return newObj;
    }
    /// <summary>
    /// 進(jìn)對象池
    /// </summary>
    /// <param name="obj">要加入的對象</param>
    public void JoinPool(GameObject obj)
    {
        //隱藏對象
        obj.SetActive(false);
        //去掉對象名稱后的‘(Clone)’
        string objName = obj.name.Substring(0, obj.name.Length - 7);
        //首先判斷字典中是否已經(jīng)有了該對象
        if (pools.ContainsKey(objName))
        {
            //有了,就添加到對應(yīng)鍵的集合里
            pools[objName].Add(obj);
        }
        else
        {
            //沒有,添加新的鍵值對
            pools.Add(objName, new List<GameObject>() {obj});
        }
    }
}


該腳本可以添加到創(chuàng)建的空物體身上博杖,注意游戲場景中必須要有帶有碰撞器的對象存在椿胯,不然,射線射誰呢剃根?

測試代碼

using UnityEngine;
using System.Collections;
//游戲控制腳本哩盲,可以添加到創(chuàng)建的空物體身上
public class GameController : MonoBehaviour
{   
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //從攝像機(jī)發(fā)出一條射線
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            //是否碰撞到帶有碰撞器的對象
            if (Physics.Raycast(ray, out hit, Mathf.Infinity))
            {       
                     //從對象池中提取對象     
                    GameObject currentObj = ObjectPoolSingleton.Instance.OutPool("Sphere",
                        Camera.main.transform.position, Quaternion.identity);
                    //球?qū)ο蟮乃俣纫跏蓟癁?,不然,會在原來基礎(chǔ)上再次添加力
                    currentObj.GetComponent<Rigidbody>().velocity = Vector3.zero;
                   //給對象一個力
                    currentObj.GetComponent<Rigidbody>().AddForce(ray.direction*1200);
                }
            }
        }
    }
}

該腳本掛載到球預(yù)設(shè)體身上(注意:球要添加剛體組件种冬,需要添加力镣丑,并且該預(yù)設(shè)體要放在Resources文件夾下,需要動態(tài)加載娱两,名稱要與你提取對象所傳入的字符串名稱相同)

using UnityEngine;
using System.Collections;
//該腳本掛載到球預(yù)設(shè)體身上(球要添加剛體組件,需要添加力)
public class Bullet : MonoBehaviour {
//注意:必須OnEnable回調(diào)函數(shù)里金吗,此函數(shù)在腳本生命周期里是可以循環(huán)調(diào)用的十兢,對象SetActive(true)
//時,就會調(diào)用
    void OnEnable()
    {
        StartCoroutine("Join");
    }
    IEnumerator Join()
    {
        yield return new WaitForSeconds(2.5f);
        //延時2.5S后進(jìn)對象池摇庙,你就看不見了
        ObjectPoolSingleton.Instance.JoinPool(gameObject);
    }
}

寫在最后

    ###代碼虐我千百遍旱物,催我快點找初戀###
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卫袒,隨后出現(xiàn)的幾起案子宵呛,更是在濱河造成了極大的恐慌,老刑警劉巖夕凝,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宝穗,死亡現(xiàn)場離奇詭異,居然都是意外死亡码秉,警方通過查閱死者的電腦和手機(jī)逮矛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來转砖,“玉大人须鼎,你說我怎么就攤上這事「幔” “怎么了晋控?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長姓赤。 經(jīng)常有香客問我赡译,道長,這世上最難降的妖魔是什么模捂? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任捶朵,我火速辦了婚禮,結(jié)果婚禮上狂男,老公的妹妹穿的比我還像新娘综看。我一直安慰自己,他們只是感情好岖食,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布红碑。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪析珊。 梳的紋絲不亂的頭發(fā)上羡鸥,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機(jī)與錄音忠寻,去河邊找鬼惧浴。 笑死,一個胖子當(dāng)著我的面吹牛奕剃,可吹牛的內(nèi)容都是我干的衷旅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼纵朋,長吁一口氣:“原來是場噩夢啊……” “哼柿顶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起操软,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤嘁锯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后聂薪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體家乘,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年胆建,在試婚紗的時候發(fā)現(xiàn)自己被綠了烤低。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡笆载,死狀恐怖扑馁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凉驻,我是刑警寧澤腻要,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站涝登,受9級特大地震影響雄家,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胀滚,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一趟济、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咽笼,春花似錦顷编、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽双肤。三九已至,卻和暖如春钮惠,著一層夾襖步出監(jiān)牢的瞬間茅糜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工素挽, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留蔑赘,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓毁菱,卻偏偏與公主長得像米死,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贮庞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容