你使用對(duì)象池了嗎

什么是對(duì)象池?
對(duì)象池汹胃,簡(jiǎn)單的說(shuō)就是一種為了避免重復(fù)創(chuàng)建婶芭,刪除對(duì)象的解決方案。它可以通過(guò)復(fù)用游戲?qū)ο笞偶ⅲ欢ǔ潭壬咸岣哂螒蛐阅芟苊鈨?nèi)存消耗,特別針對(duì)任何頻繁創(chuàng)建刪除對(duì)象的情景宰掉。這符合了性能優(yōu)化中對(duì)腳本優(yōu)化的理念呵哨。是居家旅行...哦不...游戲開(kāi)發(fā)必備技能赁濒。
對(duì)象池的實(shí)現(xiàn)原理?
創(chuàng)建復(fù)用對(duì)象的集合孟害,通過(guò)查找和設(shè)置集合元素的active狀態(tài)拒炎,達(dá)到和創(chuàng)建、刪除一樣的視覺(jué)效果纹坐。



這里先通過(guò)一個(gè)射擊子彈的簡(jiǎn)單例子枝冀,從不用對(duì)象池,到給子彈創(chuàng)建對(duì)象池耘子,去繁就簡(jiǎn)的一步步呈現(xiàn)對(duì)象池使用過(guò)程果漾,深化理解。


不用對(duì)象池的小白腳本
Control.cs

...
public class Control:MonoBehaviour{
     public  GameObject bulletPrb;
     void Update(){
          if(Input.GetMouseButton(0))
                  Fire();
  }
     void Fire(){
      Instantiate(bulletPrb);
  }
}

Bullet.cs

...
public class Bullet:Monobehaviour{
     void Start(){
      Invoke("Destroy",2);
  }
     void Destroy(){
      Destroy(gameObject);  
  }
}

這里很容易的腦補(bǔ)出Hierarchry下,bullet對(duì)象一直在創(chuàng)建谷誓,銷(xiāo)毀绒障,創(chuàng)建,銷(xiāo)毀捍歪。户辱。。

使用對(duì)象池的一階腳本
Control.cs

...
using System.Collections.Generic;

public class Control:MonoBehaviour{
     public  GameObject bulletPrb;

     public int poolingCapacity = 20;
     public List<GameObject> pool;
   
     void Start(){                 //創(chuàng)建對(duì)象池糙臼,并將對(duì)象設(shè)為不可見(jiàn)
          pool = new List<GameObject>()
          for(int i=0 ; i<poolingCapacity;i++)
                { 
                    GameObject bullet = Instantiate(bulletPrb);
                    pool.Add(bullet); 
                    pool[i].SetActive(false);
                }         
     }
     void Update(){
          if(Input.GetMouseButton(0))
                  Fire();
     }
     void Fire(){               
         //Instantiate(bulletPrb,transform.position,Quternion.identity);

         for(int i = 0 ; i < pool.Count; i++)
         {        //自動(dòng)搜索對(duì)象池中失活的對(duì)象并激活顯示
                 if ( !pool[i].activeinHierarchy )
                     {
                          pool[i].transform.position = transform.position;
                          pool[i].transform.rotation = transform.rotation;
                          pool[i].SetActive(true);
                          break;
                     }
         }
  }
}

Bullet.cs

...
public class Bullet:Monobehaviour{
     void OnEnable(){
      Invoke("Destroy",2);
  }
     void Destroy(){
       //Destory(gameObject);
       gameObject.SetActive(false);    //只要隱藏掉就好庐镐,對(duì)象還在對(duì)象池中
  }
     void OnDisable{
        CancelInvoke();
  }
}

這樣對(duì)象池的功能算是實(shí)現(xiàn)了。然而它是被構(gòu)建在控制腳本中的变逃,這樣顯然不行必逆。這就像編程小白把所有語(yǔ)句寫(xiě)在主函數(shù)中一樣,這不符合面向?qū)ο蟮乃枷肜柯遥∫虼嗣迹枰谌?/p>

使用對(duì)象池的二階腳本
新建一個(gè)ObjectBulletPool.cs 并掛載到新建的空物體ObjectPooler上

 ...
using System.Collections.Generic
public class ObjectPool: MonoBehaviour{
        public static ObjectPool current;

        public GameObject objectPrb;          //將被放入對(duì)象池中的預(yù)制體
        public int poolCapacity = 20;
        public List<GameObject> pool;
        public bool willgrow = true;           //池子容量不夠時(shí),是否自動(dòng)擴(kuò)展池子

        void Awake(){
            current = this;
     }
         void Start(){
             for(int i = 0 ; i<poolCapacity ; i++)
              {
                  GameObject obj = Instantiate(objectPrb);
                  pool.Add(obj);
                  obj.SetActive(false);
              }
     }
         public GameObject GetPooledObject(){
            for( int i = 0 ; i<pool.Count ; i++)    //遍歷對(duì)象池凰棉,將未激活的對(duì)象傳遞出去
            {
                if ( ! pool[i].activeInHierarchy )
                        return pool[i];
            }
            if  ( willgrow )  //當(dāng)池子中所有對(duì)象都激活了损拢,但是還想激活顯示對(duì)象時(shí),擴(kuò)展池子
            {
                GameObject obj = Instantiate(objectPrb);
                pool.Add(obj);
                obj.SetActive(false);
                return obj;
            }
           return null;
     } 
}

簡(jiǎn)化 Control.cs

...
using System.Collections.Generic;

public class Control:MonoBehaviour{
/*
     public  GameObject bulletPrb;
     public int poolingCapacity = 20;
     public List<GameObject> pool;
   
     void Start(){                 //創(chuàng)建對(duì)象池撒犀,并將對(duì)象設(shè)為不可見(jiàn)
          pool = new List<GameObject>()
           for(int i=0 ; i<poolingCapacity;i++)
               { 
                    GameObject bullet = Instantiate(bulletPrb);
                   pool.Add(bullet); 
                 pool[i].SetActive(false);
             }         
     }
*/
     void Update(){
          if(Input.GetMouseButton(0))
                  Fire();
     }
     void Fire(){               
         //Instantiate(bulletPrb,transform.position,Quternion.identity);
        /*
         for(int i = 0 ; i < pool.Count; i++)
         {        //自動(dòng)搜索對(duì)象池中失活的對(duì)象并激活顯示
                 if ( !pool[i].activeinHierarchy )
                     {
                          pool[i].transform.position = transform.position;
                          pool[i].transform.rotation = transform.rotation;
                          pool[i].SetActive(true);
                          break;
                     }
          }
        */
            //獲取未激活對(duì)象福压,激活顯示
          GameObject obj = ObjectPool.current.GetPooledObject();  
          if (obj == null) return;
          obj.transform.position = transform.position;
          obj.transform.rotation = transform.rotation;
          obj.SetActive(true);
  }
}

不用改 Bullet.cs

...
public class Bullet:Monobehaviour{
     void OnEnable(){
      Invoke("Destroy",2);
  }
     void Release(){
       //Destory(gameObject);
       gameObject.SetActive(false);    //只要隱藏掉就好,對(duì)象“回到”對(duì)象池中
  }
     void OnDisable{
        CancelInvoke();
  }
}

多說(shuō)一句或舞,如果你能發(fā)射不同類(lèi)型的子彈怎么辦隧膏?
解決思路:將子彈類(lèi)型bulletPrb對(duì)象改成數(shù)組,在GetPooledObject()函數(shù)中傳入子彈類(lèi)型的參數(shù)嚷那,然后遍歷數(shù)組匹配子彈類(lèi)型,return出去杆煞。

小結(jié):
這個(gè)對(duì)象池其實(shí)是固定的魏宽,一旦創(chuàng)建就不用刪除腐泻,這樣便于復(fù)用創(chuàng)建好的對(duì)象。使用對(duì)象其實(shí)就是在對(duì)象池中搜索沒(méi)有active的對(duì)象并激活獲取到它好進(jìn)行操作队询。釋放對(duì)象就是讓他失活派桩,好被以后搜索復(fù)用嬉探。
Ok,看到這里年栓,對(duì)象池的基本用法就掌握了,在實(shí)際項(xiàng)目中需求會(huì)更加多變滔灶,但是萬(wàn)變不離本質(zhì)送膳。高階運(yùn)用也是從低階進(jìn)化的员魏!



高階運(yùn)用請(qǐng)看這位老兄的文章:unity中的通用對(duì)象池

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叠聋,隨后出現(xiàn)的幾起案子撕阎,更是在濱河造成了極大的恐慌,老刑警劉巖碌补,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虏束,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡厦章,警方通過(guò)查閱死者的電腦和手機(jī)镇匀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)袜啃,“玉大人汗侵,你說(shuō)我怎么就攤上這事∧抑瑁” “怎么了晃择?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)也物。 經(jīng)常有香客問(wèn)我宫屠,道長(zhǎng),這世上最難降的妖魔是什么滑蚯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任浪蹂,我火速辦了婚禮,結(jié)果婚禮上告材,老公的妹妹穿的比我還像新娘坤次。我一直安慰自己,他們只是感情好斥赋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布缰猴。 她就那樣靜靜地躺著,像睡著了一般疤剑。 火紅的嫁衣襯著肌膚如雪滑绒。 梳的紋絲不亂的頭發(fā)上闷堡,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音疑故,去河邊找鬼杠览。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纵势,可吹牛的內(nèi)容都是我干的踱阿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钦铁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼软舌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起育瓜,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤葫隙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后躏仇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體恋脚,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年焰手,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了糟描。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡书妻,死狀恐怖船响,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情躲履,我是刑警寧澤见间,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站工猜,受9級(jí)特大地震影響米诉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜篷帅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一史侣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魏身,春花似錦惊橱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春掉房,著一層夾襖步出監(jiān)牢的瞬間茧跋,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工卓囚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诅病。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓哪亿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贤笆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝇棉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)芥永,斷路器篡殷,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,970評(píng)論 6 13
  • Unity 對(duì)象池技術(shù) 為什么使用對(duì)象池? 在我們開(kāi)發(fā)中埋涧,往往會(huì)遇見(jiàn)需要不斷創(chuàng)建和銷(xiāo)毀同一物體的情況板辽。(如飛機(jī)大戰(zhàn)...
    胤醚貔貅閱讀 788評(píng)論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法棘催,內(nèi)部類(lèi)的語(yǔ)法劲弦,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法醇坝,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,631評(píng)論 18 399
  • 世界上本沒(méi)有節(jié),過(guò)的人多了宋距,也就成了節(jié) -------一個(gè)吃貨的自白 這年...
    O2O頭條閱讀 612評(píng)論 0 0