技術(shù) 117871561 交流
cocoscreator2.4.x版本
內(nèi)存管理
官方參考文檔:https://docs.cocos.com/creator/manual/zh/asset-manager/release-manager.html?q=
cocos2.4版本后 引擎通過cc.assetManager管理所有的 資源棒掠,在資源加載完成后,會(huì)被臨時(shí)緩存到 cc.assetManager 中,以便下次復(fù)用。但是這也會(huì)造成內(nèi)存和顯存的持續(xù)增長(zhǎng),所以有些資源如果不需要用到磺樱,可以通過 自動(dòng)釋放 或者 手動(dòng)釋放 的方式進(jìn)行釋放。釋放資源將會(huì)銷毀資源的所有內(nèi)部屬性,比如渲染層的相關(guān)數(shù)據(jù)煎殷,并移出緩存,從而釋放內(nèi)存和顯存(對(duì)紋理而言)腿箩。
內(nèi)存管理機(jī)制:
cocoscreator的內(nèi)存管理機(jī)制 其實(shí)就是 對(duì) cc.asset的實(shí)例 的引用計(jì)數(shù)的管理 豪直,通過對(duì)cc.asset實(shí)例(資源如texture,spriteframe)的引用計(jì)數(shù)的增減 來判斷是否 釋放 資源。
釋放檢查
為了避免錯(cuò)誤釋放正在使用的資源造成渲染或其他問題珠移,Creator 會(huì)在自動(dòng)釋放資源之前進(jìn)行一系列的檢查弓乙,只有檢查通過了,才會(huì)進(jìn)行自動(dòng)釋放钧惧。
如果資源的引用計(jì)數(shù)為 0暇韧,即沒有其他地方引用到該資源,則無需做后續(xù)檢查浓瞪,直接摧毀該資源懈玻,移除緩存。
資源一旦被移除乾颁,會(huì)同步觸發(fā)其依賴資源的釋放檢查涂乌,將移除緩存后的資源的 直接 依賴資源(不包含后代)的引用都減 1,并同步觸發(fā)釋放檢查英岭。
如果資源的引用計(jì)數(shù)不為 0湾盒,即存在其他地方引用到該資源,此時(shí)需要進(jìn)行循環(huán)引用檢查诅妹,避免出現(xiàn)自己的后代引用自己的情況历涝。如果循環(huán)引用檢查完成之后引用計(jì)數(shù)仍不為 0,則終止釋放,否則直接摧毀該資源荧库,移除緩存堰塌,并觸發(fā)其依賴資源的釋放檢查(同步驟 2)。
實(shí)際操作
有 cc.Asset 實(shí)例都擁有成員函數(shù) cc.Asset.addRef 和 cc.Asset.decRef分衫,分別用于增加和減少引用計(jì)數(shù)场刑。一旦引用計(jì)數(shù)為零,Creator 會(huì)對(duì)資源進(jìn)行自動(dòng)釋放(需要先通過釋放檢查蚪战,具體可參考下部分內(nèi)容的介紹)
start () {
cc.resources.load('images/background', cc.Texture2D, (err, texture) => {
this.texture = texture;
// 當(dāng)需要使用資源時(shí)牵现,增加其引用
texture.addRef();
// ...
});
}
onDestroy () {
// 當(dāng)不需要使用資源時(shí),減少引用
// Creator 會(huì)在調(diào)用 decRef 后嘗試對(duì)其進(jìn)行自動(dòng)釋放,釋放前會(huì)進(jìn)行上面所說的釋放檢查步驟
this.texture.decRef();
}
為什么會(huì)有 資源的靜態(tài)引用管理和 資源的動(dòng)態(tài)引用管理邀桑?
Asset Manager 提供了一套基于引用計(jì)數(shù)的資源釋放機(jī)制瞎疼,讓開發(fā)者可以簡(jiǎn)單高效地釋放資源,不用擔(dān)心項(xiàng)目規(guī)模的急劇膨脹壁畸。需要說明的是 Asset Manager 只會(huì)自動(dòng)統(tǒng)計(jì)資源之間的靜態(tài)引用贼急,并不能真實(shí)地反應(yīng)資源在游戲中被動(dòng)態(tài)引用的情況,動(dòng)態(tài)引用還需要開發(fā)者進(jìn)行控制以保證資源能夠被正確釋放捏萍。原因如下:
1太抓,JavaScript 是擁有垃圾回收機(jī)制的語言,會(huì)對(duì)其內(nèi)存進(jìn)行管理令杈,在瀏覽器環(huán)境中引擎無法知道某個(gè)資源是否被銷毀走敌。
2,JavaScript 無法提供賦值運(yùn)算符的重載逗噩,而引用計(jì)數(shù)的統(tǒng)計(jì)則高度依賴于賦值運(yùn)算符的重載掉丽。
cocoscreator中管理內(nèi)存的兩種方式:資源的靜態(tài)引用管理,資源的動(dòng)態(tài)引用管理
1异雁,靜態(tài)引用管理: 當(dāng)開發(fā)者在編輯器中編輯資源時(shí)(例如場(chǎng)景捶障、預(yù)制體、材質(zhì)等)片迅,需要在這些資源的屬性中配置一些其他的資源残邀,例如在材質(zhì)中設(shè)置貼圖皆辽,在場(chǎng)景的 Sprite 組件上設(shè)置 SpriteFrame柑蛇。那么這些引用關(guān)系會(huì)被記錄在資源的序列化數(shù)據(jù)中,引擎可以通過這些數(shù)據(jù)分析出依賴資源列表驱闷,像這樣的引用關(guān)系就是靜態(tài)引用耻台。
2,動(dòng)態(tài)引用管理:當(dāng)開發(fā)者在編輯器中沒有對(duì)資源做任何設(shè)置空另,而是通過代碼動(dòng)態(tài)加載資源并設(shè)置到場(chǎng)景的組件上盆耽,則資源的引用關(guān)系不會(huì)記錄在序列化數(shù)據(jù)中,引擎無法統(tǒng)計(jì)到這部分的引用關(guān)系,這些引用關(guān)系就是動(dòng)態(tài)引用摄杂。
內(nèi)存優(yōu)化
按鈕 或者 純色背景 用九宮格減少紋理加載后的內(nèi)存占用
動(dòng)畫盡量用龍骨或者spine 盡量少用 幀動(dòng)畫
壓縮紋理,參考我的另一篇文章http://www.reibang.com/p/4c5cbdf98cafcup不會(huì)緩存紋理
資源加載引用的管理坝咐,按照項(xiàng)目需要及時(shí)釋放資源 與保留常駐資源。
渲染優(yōu)化
1析恢,drawcall優(yōu)化 自動(dòng)圖集或者碎圖打成大圖 墨坚,歸類,公共/特殊場(chǎng)景映挂。設(shè)置合理的層級(jí)泽篮,增加cocos的合批渲染,減少因?yàn)閏pu的狀態(tài)切換導(dǎo)致的性能損耗參考我這篇文章《cocoscreator 2.4.x版本 drawcall優(yōu)化 第一期(掌握控制drawcall數(shù)量的必要知識(shí))》(公眾號(hào)里有 )
,2柑船, 壓縮紋理,參考我的另一篇文章《cocosCreator 壓縮紋理及詳細(xì)介紹 (性能優(yōu)化必看帽撑,改)》 減少 cup的 解碼壓力
3, 設(shè)置 合適的幀率鞍时,戰(zhàn)斗場(chǎng)景 和其他場(chǎng)景
4亏拉, label盡量 盡量不用系統(tǒng)字 用bmfont 字 (但是會(huì)有內(nèi)存消耗的缺點(diǎn)),label會(huì)打斷核批寸癌,也可以選用label的緩存模式:
1)bitmap:將文本作為靜態(tài)圖像专筷,加入動(dòng)態(tài)圖集進(jìn)行合批,缺點(diǎn)是內(nèi)容不能頻繁更新蒸苇。
2)char:將 文本拆分成字符磷蛹,并緩存到一張字符圖集中復(fù)用,適用于重復(fù)溪烤,頻繁更新的內(nèi)容
個(gè)人建議:選擇bnfont位圖字味咳。穩(wěn)定除非對(duì)內(nèi)存要求很高
5, 減少節(jié)點(diǎn)樹深度和節(jié)點(diǎn)數(shù)量
6檬嘀,合理降低紋理像素深度即 rgb/rgba像素格式(例如某些界面的紋理貼圖 采用rgba8888 有的界面貼圖用rgba4444格式)
注意:第6條僅作參考 槽驶,因?yàn)槟壳癱ocoscreator項(xiàng)目中紋理加載到內(nèi)存中 像素格式都會(huì)轉(zhuǎn)為rgba8888格式。所以 按照理論上來說 降低紋理像素深度 不會(huì)對(duì)內(nèi)存產(chǎn)生影響鸳兽。
加載優(yōu)化
1掂铐, 分幀加載,減少大量節(jié)點(diǎn)在同一幀創(chuàng)建帶來的卡頓
2揍异, 采用節(jié)點(diǎn)池機(jī)制 避免頻繁銷毀創(chuàng)建 帶來的性能 損耗
3 靜默加載 :比如在 大廳場(chǎng)景全陨,預(yù)加載游戲場(chǎng)景的資源
4,添加loading界面 衷掷,在loading的時(shí)候加載資源辱姨,加載完畢 進(jìn)入場(chǎng)景
5, 自動(dòng)圖集或者碎圖打成大圖 戚嗅,減少io 雨涛。
6枢舶, 拆分 預(yù)制體 將大的預(yù)制體 拆分成 多個(gè)小的預(yù)制體
7,scrollview 優(yōu)化 滑動(dòng)過程中動(dòng)態(tài)設(shè)置元素替久,實(shí)現(xiàn)元素資源重復(fù)使用(多見于背包和排行榜系統(tǒng)凉泄,百度一下有很多例子)
8),根據(jù)不同的功能蚯根,需求 旧困,設(shè)置 多個(gè)assetbundle,將資源稼锅,場(chǎng)景吼具,邏輯放在里面,需要時(shí)進(jìn)行加載
參考我的這篇文章《我理解的 cocosCreator asset Bundle 版本2.4.4》 (公眾號(hào)里有)
包體優(yōu)化:
一 .貼圖資源:
1)按鈕和純色背景圖用九宮格
設(shè)置:在編輯器中矩距,找到要設(shè)置的圖片拗盒,可以在純色圖片的右側(cè)屬性欄中找到 編輯 然后根據(jù)比例設(shè)置九宮格圖片的拉伸區(qū)域。
解析:一般九宮格圖片尺寸比較小锥债,當(dāng)一個(gè)純色的按鈕或者背景圖等等 需要 大尺寸的圖片時(shí) 陡蝇,這時(shí)候用九宮格圖片 就會(huì)比原尺寸圖小很多,達(dá)到縮小包體的效果哮肚。
2)合理使用jpg代替png圖片用作背景圖片
解析:同尺寸的 jpg圖片文件要比png圖片文件 小一些登夫,因?yàn)?jpg和png都是一種圖片壓縮格式,jpg為有損壓縮 png為無損壓縮允趟,所以 png要比jpg質(zhì)量要高恼策,同時(shí) 占用的存儲(chǔ)也就越多 。通常情況下項(xiàng)目中還是以png格式為主(jpg 在加載到內(nèi)存時(shí)會(huì)有一個(gè)加載峰值大概是 2-3倍左右 png也會(huì)有但是 只有1倍左右潮剪。穩(wěn)定后 所占用的內(nèi)存一樣)
3)合理復(fù)用可復(fù)用的資源
解析:在游戲項(xiàng)目中 占用 項(xiàng)目體積最多的就是紋理涣楷,所以更多的復(fù)用圖片資源 就意味著 達(dá)到相同效果情況下 項(xiàng)目的包體 就越小。
4)用龍骨和spine動(dòng)畫代替幀動(dòng)畫抗碰,減少過多資源帶來的包體影響
解析:
幀動(dòng)畫:在游戲進(jìn)行的每一幀狮斗,記錄當(dāng)先渲染圖片/精靈的位置,在目標(biāo)位置實(shí)時(shí)渲染出該精靈弧蝇。每一幀刷新渲染區(qū)域碳褒,完成一個(gè)動(dòng)畫需要比較多的圖片。
骨骼動(dòng)畫:隨著圖像渲染從CPU->GPU看疗,渲染的內(nèi)容從記錄每個(gè)精靈改為記錄需要渲染的位置沙峻。設(shè)計(jì)骨頭的頂點(diǎn),骨頭之間的聯(lián)系鹃觉。設(shè)計(jì)蒙皮(圖片精靈)专酗,蒙皮的坐標(biāo)睹逃,展示的頂點(diǎn)盗扇。骨骼動(dòng)畫通過算法計(jì)算渲染的位置來實(shí)現(xiàn)的
比較:實(shí)現(xiàn)一組相同的動(dòng)畫 骨骼動(dòng)畫 需要的資源比幀動(dòng)畫少很多祷肯,在項(xiàng)目中 使用骨骼動(dòng)畫 可以減少包體和運(yùn)行時(shí)的內(nèi)存壓力,相反疗隶,骨骼動(dòng)畫會(huì)浪費(fèi)更多的時(shí)間用于計(jì)算佑笋。也就是說 兩者是 空間與時(shí)間 互換的衡量過程。
通常情況下斑鼻,小的公司蒋纬,有可能因?yàn)槌杀驹蛘胁坏綍?huì)骨骼動(dòng)畫得美術(shù),所以還是會(huì)考慮用幀動(dòng)畫坚弱。這些需要根據(jù) 最終項(xiàng)目呈現(xiàn)出來的 體驗(yàn) 來判斷是否需要進(jìn)行優(yōu)化蜀备。
5)合理降低紋理像素深度即 rgb/rgba像素格式(例如某些界面的紋理貼圖 采用rgba8888 有的界面貼圖用rgba4444格式)
解析:紋理的像素格式?jīng)Q定了該紋理能表示的最多像素種類和數(shù)量,例如rgba8888每個(gè)顏色分量 占用8位 那么這種像素格式的 紋理 每像素占用8 * 4 = 32位 即4個(gè)字節(jié)荒叶。如果用rgba4444像素格式碾阁,每個(gè)顏色分量占用4位 那么每個(gè)像素占用4 * 4 = 16位 即2個(gè)字節(jié)。也就是說 兩張同樣大小的紋理前者要比后者多占用一般的存儲(chǔ)單位些楣。
6)壓縮圖片資源(pngyu或其他壓縮軟件)
7)如果打包成app可以嘗試選擇壓縮紋理脂凶。
解析:壓縮紋理后的文件要比 png jpg文件大好幾倍,但是 打包時(shí) 進(jìn)行壓縮后愁茁,包體相較要小很多蚕钦。
二.音效資源:
1)降低音效采樣率,聲道 (背景音樂占比最大)
三.字體資源:
1)如果用的ttf字體 鹅很,可以用fontmin裁剪 字庫
解析:字庫一般有幾兆大小 嘶居,可以通過 fontmin 輸入項(xiàng)目中用到的字,從字庫中提取就好了促煮。
2)盡可能使用系統(tǒng)字不會(huì)額外增加包體大小食听,可以用 系統(tǒng)字的緩存模式 中對(duì)應(yīng)的模式來優(yōu)化dc帶來的困擾
3)位圖字(bitmapfont),把不需要的字剔除掉(弊端污茵,內(nèi)存占用大)樱报;
解析:位圖字其實(shí)就是紋理,加載到內(nèi)存中 會(huì)占用比較大的內(nèi)存泞当。優(yōu)點(diǎn)是 速度快迹蛤。
四.引擎方面:
1)裁剪引擎,把用不到的模塊 取消勾選襟士。
五.遠(yuǎn)程加載:
1)設(shè)置遠(yuǎn)程加載文件夾為asset bundle 放在遠(yuǎn)程盗飒,用到時(shí)再去加載使用
碰撞優(yōu)化
四叉樹結(jié)合cocoscreator碰撞邏輯(百度搜索就可以找到相關(guān)的解釋)
代碼級(jí)別優(yōu)化
1,運(yùn)行速度上以空間換時(shí)間 為中心(比如Map代替數(shù)組)
2陋桂, 排序算法 用快速排序等犧牲空間 減少時(shí)間的算法 代替 選擇排序 或 冒泡排序
,3逆趣,盡量用es6新特性,功能分模塊嗜历,避免 代碼冗余宣渗,代碼簡(jiǎn)潔易懂 注釋用/***/ 避免注釋滯后抖所。
,4,數(shù)組的重置 用arr.length = 0 而不用arr = [] 因?yàn)? arr = [] 只是 將arr賦值給另一個(gè)引用 這個(gè)引用指向的是堆內(nèi)另一塊內(nèi)存 痕囱,原來arr的引用指向的內(nèi)存 依然 不會(huì)被釋放掉