最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用CocosCreator對(duì)象池

 更新時(shí)間:2021年04月14日 15:16:11   作者:戰(zhàn) 勝  
這篇文章主要介紹了CocosCreator對(duì)象池,對(duì)性能有研究的同學(xué),要著重看一下

前言:

在運(yùn)行時(shí)進(jìn)行節(jié)點(diǎn)的創(chuàng)建( cc.instantiate )和銷毀( node.destroy )操作是非常耗費(fèi)性能的,因此我們?cè)诒容^復(fù)雜的場(chǎng)景中,通常只有在場(chǎng)景初始化邏輯( onLoad )中才會(huì)進(jìn)行節(jié)點(diǎn)的創(chuàng)建,在切換場(chǎng)景時(shí)才會(huì)進(jìn)行節(jié)點(diǎn)的銷毀。如果制作有大量敵人或子彈需要反復(fù)生成和被消滅的動(dòng)作類游戲,我們要如何在游戲進(jìn)行過程中隨時(shí)創(chuàng)建和銷毀節(jié)點(diǎn)呢?這里就需要對(duì)象池的幫助了。

對(duì)象池就是一組可回收的節(jié)點(diǎn)對(duì)象,我們通過創(chuàng)建cc.NodePool的實(shí)例來(lái)初始化一種節(jié)點(diǎn)的對(duì)象池。通常當(dāng)我們有多個(gè) prefab 需要實(shí)例化時(shí),應(yīng)該為每個(gè) prefab 創(chuàng)建一個(gè) cc.NodePool 實(shí)例。

當(dāng)我們需要?jiǎng)?chuàng)建節(jié)點(diǎn)時(shí),向?qū)ο蟪厣暾?qǐng)一個(gè)節(jié)點(diǎn),如果對(duì)象池里有空閑的可用節(jié)點(diǎn),就會(huì)把節(jié)點(diǎn)返回給用戶,用戶通過node.addChild將這個(gè)新節(jié)點(diǎn)加入到場(chǎng)景節(jié)點(diǎn)樹中。
當(dāng)我們需要銷毀節(jié)點(diǎn)時(shí),調(diào)用對(duì)象池實(shí)例的put(node) 方法,傳入需要銷毀的節(jié)點(diǎn)實(shí)例,對(duì)象池會(huì)自動(dòng)完成把節(jié)點(diǎn)從場(chǎng)景節(jié)點(diǎn)樹中移除的操作,然后返回給對(duì)象池。

這樣就實(shí)現(xiàn)了少數(shù)節(jié)點(diǎn)的循環(huán)利用。

具體操作

第一步:準(zhǔn)備好 Prefab

把你想要?jiǎng)?chuàng)建的節(jié)點(diǎn)事先設(shè)置好并做成 Prefab 資源,有些朋友可能不會(huì)制作預(yù)制體?
(只需要將資源管理器里的資源 拉拽到 層級(jí)管理器中 然后 將節(jié)點(diǎn)在拉拽回 資源管理器)
這樣就完成預(yù)制體的創(chuàng)建了!

第二步:初始化對(duì)象池

在場(chǎng)景加載的初始化腳本中,我們可以將需要數(shù)量的節(jié)點(diǎn)創(chuàng)建出來(lái),并放進(jìn)對(duì)象池:

properties: {
    enemyPrefab: cc.Prefab  // 所需要的預(yù)制體
},
onLoad: function () {
    //  創(chuàng)建對(duì)象池
    this.enemyPool = new cc.NodePool();
    
    let initCount = 5;
    for (let i = 0; i < initCount; ++i) {
        let enemy = cc.instantiate(this.enemyPrefab); // 創(chuàng)建節(jié)點(diǎn)
        this.enemyPool.put(enemy); // 通過 put 接口放入對(duì)象池
    }
}

對(duì)象池里需要的初始節(jié)點(diǎn)數(shù)量可以根據(jù)游戲的需要來(lái)控制,即使我們對(duì)初始節(jié)點(diǎn)數(shù)量的預(yù)估不準(zhǔn)確也不要緊,后面我們會(huì)進(jìn)行處理。

第三步:從對(duì)象池請(qǐng)求對(duì)象

接下來(lái)在我們的運(yùn)行時(shí)代碼中就可以用下面的方式來(lái)獲得對(duì)象池中儲(chǔ)存的對(duì)象了:

createEnemy: function (parentNode) {
    let enemy = null;
    if (this.enemyPool.size() > 0) { // 通過 size 接口判斷對(duì)象池中是否有空閑的對(duì)象
        // get()獲取對(duì)象
        enemy = this.enemyPool.get();
        
    } else { // 如果沒有空閑對(duì)象,也就是對(duì)象池中備用對(duì)象不夠時(shí),我們就用 cc.instantiate 重新創(chuàng)建
        enemy = cc.instantiate(this.enemyPrefab);
    }
    enemy.parent = parentNode; // 將生成的敵人加入節(jié)點(diǎn)樹
    enemy.getComponent('Enemy').init(); //接下來(lái)就可以調(diào)用 enemy 身上的腳本進(jìn)行初始化
}

安全使用對(duì)象池的要點(diǎn)就是在 get 獲取對(duì)象之前,永遠(yuǎn)都要先用 size 來(lái)判斷是否有可用的對(duì)象,如果沒有就使用正常創(chuàng)建節(jié)點(diǎn)的方法,雖然會(huì)消耗一些運(yùn)行時(shí)性能,但總比游戲崩潰要好!另一個(gè)選擇是直接調(diào)用 get ,如果對(duì)象池里沒有可用的節(jié)點(diǎn),會(huì)返回 null ,在這一步進(jìn)行判斷也可以。

第四步:將對(duì)象返回對(duì)象池

當(dāng)我們殺死敵人時(shí),需要將敵人節(jié)點(diǎn)退還給對(duì)象池,以備之后繼續(xù)循環(huán)利用,我們用這樣的方法:

onEnemyKilled: function (enemy) {
    // enemy 應(yīng)該是一個(gè) cc.Node
    this.enemyPool.put(enemy); // 和初始化時(shí)的方法一樣,將節(jié)點(diǎn)放進(jìn)對(duì)象池,這個(gè)方法會(huì)同時(shí)調(diào)用節(jié)點(diǎn)的 removeFromParent
}

這樣我們就完成了一個(gè)完整的循環(huán),主角需要刷多少怪都不成問題了!將節(jié)點(diǎn)放入和從對(duì)象池取出的操作不會(huì)帶來(lái)額外的內(nèi)存管理開銷,因此只要是可能,應(yīng)該盡量去利用。

第五步:使用組件來(lái)處理回收和復(fù)用的事件

使用構(gòu)造函數(shù)創(chuàng)建對(duì)象池時(shí),可以指定一個(gè)組件類型或名稱,作為掛載在節(jié)點(diǎn)上用于處理節(jié)點(diǎn)回收和復(fù)用事件的組件。

在創(chuàng)建對(duì)象池時(shí)可以用:

 let menuItemPool = new cc.NodePool('MenuItem');  // 指定一個(gè)組件類型

這樣當(dāng)使用 menuItemPool.get() 獲取節(jié)點(diǎn)后,就會(huì)調(diào)用 MenuItem 里的 reuse方法,完成點(diǎn)擊事件的注冊(cè)。
當(dāng)使用menuItemPool.put(menuItemNode)回收節(jié)點(diǎn)后,會(huì)調(diào)用 MenuItem 里的 unuse方法,完成點(diǎn)擊事件的反注冊(cè)。

cc.Class({
    extends: cc.Component,
    onLoad: function () {
        this.node.selected = false;
        this.node.on(cc.Node.EventType.TOUCH_END, this.onSelect, this.node);
    },
    // put() 收回對(duì)象池時(shí)會(huì)調(diào)用
    unuse: function () {
        this.node.off(cc.Node.EventType.TOUCH_END, this.onSelect, this.node);
    },
    // get()獲取對(duì)象池內(nèi)對(duì)象時(shí)會(huì)調(diào)用
    reuse: function () {
        this.node.on(cc.Node.EventType.TOUCH_END, this.onSelect, this.node);
    }
});

另外 cc.NodePool.get() 可以傳入任意數(shù)量類型的參數(shù),這些參數(shù)會(huì)被原樣傳遞給 reuse 方法:

// BulletManager.js
let myBulletPool = new cc.NodePool('Bullet'); //創(chuàng)建子彈對(duì)象池
let newBullet = myBulletPool.get(this); // 傳入 manager 的實(shí)例,用于之后在子彈腳本中回收子彈

// Bullet.js
reuse (bulletManager) {
    this.bulletManager = bulletManager; // get 中傳入的管理類實(shí)例
}
hit () {
    this.bulletManager.put(this.node); // 通過之前傳入的管理類實(shí)例回收子彈
}

第六步:清除對(duì)象池

如果對(duì)象池中的節(jié)點(diǎn)不再被需要,我們可以手動(dòng)清空對(duì)象池,銷毀其中緩存的所有節(jié)點(diǎn):

myPool.clear(); // 調(diào)用這個(gè)方法就可以清空對(duì)象池

當(dāng)對(duì)象池實(shí)例不再被任何地方引用時(shí),引擎的垃圾回收系統(tǒng)會(huì)自動(dòng)對(duì)對(duì)象池中的節(jié)點(diǎn)進(jìn)行銷毀和回收。但這個(gè)過程的時(shí)間點(diǎn)不可控,另外如果其中的節(jié)點(diǎn)有被其他地方所引用,也可能會(huì)導(dǎo)致內(nèi)存泄露,所以最好在切換場(chǎng)景或其他不再需要對(duì)象池的時(shí)候手動(dòng)調(diào)用 clear 方法來(lái)清空緩存節(jié)點(diǎn)。

以上就是如何使用CocosCreator對(duì)象池的詳細(xì)內(nèi)容,更多關(guān)于CocosCreator對(duì)象池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • javascript 面向?qū)ο髮?shí)戰(zhàn)思想分享

    javascript 面向?qū)ο髮?shí)戰(zhàn)思想分享

    萬(wàn)物皆對(duì)象,所以,任何事物都是有特征(屬性)和動(dòng)作(方法)的,一般拿到一份需求分檔,或者你瀏覽一個(gè)網(wǎng)頁(yè)看到一個(gè)畫面的時(shí)候,腦子里就要有提煉出來(lái)的屬性和方法的能力,那你才是合格的
    2017-09-09
  • script標(biāo)簽屬性type與language使用選擇

    script標(biāo)簽屬性type與language使用選擇

    很多使用javascript的朋友都有著這樣一個(gè)問題:script標(biāo)簽屬性type與language使用應(yīng)如何選擇,為解決此疑惑,本文詳細(xì)整理了一下,需要的朋友可以參考下
    2012-12-12
  • 當(dāng)某個(gè)文本框成為焦點(diǎn)時(shí)即清除文本框內(nèi)容

    當(dāng)某個(gè)文本框成為焦點(diǎn)時(shí)即清除文本框內(nèi)容

    這篇文章主要介紹了當(dāng)某個(gè)文本框成為焦點(diǎn)時(shí)如何清除文本框內(nèi)容,需要的朋友可以參考下
    2014-04-04
  • 如何給ss bash 寫一個(gè) WEB 端查看流量的頁(yè)面

    如何給ss bash 寫一個(gè) WEB 端查看流量的頁(yè)面

    由于剛畢業(yè)的窮大學(xué)生,和朋友合租了一臺(tái)服務(wù)器開了多個(gè)端口提供 ss 服務(wù),懶得配置 ss-panel,就使用了 ss-bash 來(lái)監(jiān)控不同端口的流量,但每次都要等上服務(wù)器才能看到流量使用情況,很麻煩,于是就寫了個(gè)簡(jiǎn)單的頁(yè)面來(lái)提供 WEB 訪問,具體內(nèi)容一起通過本文學(xué)習(xí)吧
    2017-03-03
  • 在Layui中實(shí)現(xiàn)開關(guān)按鈕的效果實(shí)例

    在Layui中實(shí)現(xiàn)開關(guān)按鈕的效果實(shí)例

    今天小編就為大家分享一篇在Layui中實(shí)現(xiàn)開關(guān)按鈕的效果實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2019-09-09
  • 淺析對(duì)JS中方法unshift和push方法的理解

    淺析對(duì)JS中方法unshift和push方法的理解

    JavaScript中的`unshift`和`push`方法用于在數(shù)組的開始和結(jié)尾添加元素,它們會(huì)直接修改原數(shù)組并返回新的數(shù)組長(zhǎng)度,本文介紹JS中方法unshift和push方法的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2024-12-12
  • Bootstrap每天必學(xué)之按鈕(一)

    Bootstrap每天必學(xué)之按鈕(一)

    Bootstrap每天必學(xué)之按鈕,本文講解的就是大家最為常用的button按鈕的樣式,感興趣的小伙伴們可以參考一下
    2015-11-11
  • js中prototype用法詳細(xì)介紹

    js中prototype用法詳細(xì)介紹

    這篇文章詳細(xì)介紹了js中prototype用法及實(shí)例,有需要的朋友可以參考一下
    2013-11-11
  • javascript頁(yè)面渲染速度測(cè)試腳本分享

    javascript頁(yè)面渲染速度測(cè)試腳本分享

    這篇文章主要介紹了javascript頁(yè)面渲染速度測(cè)試腳本,計(jì)算瀏覽器渲染HTML頁(yè)面所需要的時(shí)間,需要的朋友可以參考下
    2014-04-04
  • js添加事件的通用方法推薦

    js添加事件的通用方法推薦

    下面小編就為大家?guī)?lái)一篇js添加事件的通用方法推薦。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2016-05-05

最新評(píng)論

海城市| 宁南县| 广州市| 友谊县| 诸城市| 长岛县| 潜山县| 申扎县| 绥化市| 双城市| 额敏县| 东港市| 二连浩特市| 团风县| 贵州省| 南宁市| 泰和县| 柳江县| 韶关市| 林甸县| 青阳县| 安阳县| 德阳市| 镇江市| 虎林市| 囊谦县| 徐州市| 噶尔县| 洪江市| 扎囊县| 凌海市| 武鸣县| 新民市| 佛坪县| 宁海县| 镇雄县| 灵石县| 马龙县| 涞源县| 江阴市| 高雄县|