我們?cè)趧?chuàng)建精靈時(shí),cocos2d首先會(huì)根據(jù)文件名在TextureCache里面找有沒(méi)有這個(gè)紋理,如果有,就直接使用,如果沒(méi)有,就會(huì)加載這塊紋理,然后保存在TextureCache里面,而使用createWithSpriteFrameName創(chuàng)建精靈時(shí)不會(huì)去加載紋理,如果找不到,就會(huì)返回空指針。
在TextureCache這個(gè)單例有個(gè)方法removeUnusedTextures()用來(lái)釋放未使用的紋理。所以我們一般在Scene的OnExit()里面調(diào)用這個(gè)函數(shù),來(lái)移除未使用紋理。
為什么不在按鈕點(diǎn)下的時(shí)候就移除紋理,而在OnExit()里面移除呢?這和MainRoop有關(guān),我們不知道觸摸事件是在每一幀開(kāi)始還是結(jié)尾處理的。如果在每一幀開(kāi)始就處理了,這會(huì)造成釋放未使用的紋理,而在update里面剛好使用了被釋放的紋理,并且是使用createWithSpriteFrameName創(chuàng)建的精靈,就會(huì)返回空指針,造成異常。而Scene的OnExit在這一幀的所有update執(zhí)行完后才調(diào)用,而且這個(gè)場(chǎng)景中和節(jié)點(diǎn)綁定的update也會(huì)全部被移除,這樣就不會(huì)出現(xiàn)上述情況了,安全性就大大提高了。
我們?cè)賮?lái)說(shuō)說(shuō)紋理管理,在OnExit()中釋放紋理在小項(xiàng)目里面影響不大,但是在大一點(diǎn)的項(xiàng)目里面,我們每次切換場(chǎng)景都移除未使用的紋理就會(huì)造成進(jìn)入下一個(gè)頁(yè)面的時(shí)候卡頓一下。這個(gè)時(shí)候,就需要使用過(guò)度場(chǎng)景。過(guò)度場(chǎng)景過(guò)多會(huì)影響玩家的游戲體驗(yàn)。
這里提供一種優(yōu)化方案來(lái)處理這個(gè)問(wèn)題。我們每次在進(jìn)入場(chǎng)景的時(shí)候,只加載必須使用的紋理(如背景圖,人物),異步加載其他非必須紋理(如設(shè)置界面,這樣就可以避免打開(kāi)子界面的時(shí)候卡頓),這樣就可以很快進(jìn)入游戲場(chǎng)景,從而避免使用過(guò)度場(chǎng)景。同時(shí)異步隊(duì)列里面加載下一個(gè)場(chǎng)景的必須資源,這樣,進(jìn)入下一個(gè)場(chǎng)景時(shí)就不會(huì)去加載資源,只會(huì)異步加載其他非必須資源,從而使場(chǎng)景切換變得流暢。
這個(gè)方案幾個(gè)缺點(diǎn)。
1、每個(gè)界面使用createWithSpriteFrameName都要去檢測(cè)這個(gè)界面的紋理有沒(méi)有加載,如果沒(méi)有加載,立刻同步加載。
2、這里需要注意加載完后占用內(nèi)存的大小,如果過(guò)大,就需要舍棄異步加載部分資源、或者只加載非必須紋理、或者只加載下個(gè)場(chǎng)景非必須紋理(如果玩家點(diǎn)開(kāi)其他子界面過(guò)多還是會(huì)造成占用內(nèi)存過(guò)高)。同時(shí)注意移除下一個(gè)不可能進(jìn)入的場(chǎng)景的紋理。比如,a場(chǎng)景進(jìn)入b場(chǎng)景,b場(chǎng)景進(jìn)入c場(chǎng)景,c場(chǎng)景不能直接進(jìn)入a場(chǎng)景,需要進(jìn)入b場(chǎng)景才能回到a場(chǎng)景。在進(jìn)入c場(chǎng)景后就可以把a(bǔ)場(chǎng)景的必須紋理移除掉了。
3、每個(gè)場(chǎng)景使用的紋理必須明確。
這里有一個(gè)使用模板: https://pan.baidu.com/s/1c2o5lN6