寫這邊文章的主要目的是爲了理解使用cocos3d-js開發app時,瀏覽器調試與真機狀況不一致的緣由程序員
1、瀏覽器中內存管理機制算法
HTML5版本運行時,整個遊戲只存在JS腳本與一些必要的資源文件,這時候內存管理是由JS內存管理機制來控制的。瀏覽器
JS內存管理有一套很是智能的機制,稱爲垃圾回收器。垃圾回收器有兩種策略--引用計數與標記清除,判斷某個對象是否可回收,app
而後週期性啓動回收線程把以前已標記爲可回收的對象銷燬回收。this
引用計數:引用計數使用系統記錄一個對象被引用的次數,當對象被引用的次數變爲0時,該對象即被視做垃圾而被回收;spa
這是一種比較簡單高效的策略,可是引用計數對循環引用的狀況難以處理;這時候就引入了另外一種策略:標記清除線程
標記清除:這樣的方法是產生跟蹤對象的關係圖,而後進行垃圾回收。其算法是首先將程序中正在使用的對象視爲「根對象」,3d
從根對象開始查找它們所引用的堆空間,並在這些堆空間上作標記,可是這種方法每每會產生比較大的計算開銷;指針
不斷怎麼說,JS的內存管理足夠智能,使得程序員能夠沒必要關注內存管理,反而要關注如何讓JS的內存管理機制可以搞高效的調試
運轉。
2、JSB
cocos2d-js在發佈爲app時,使用的是JSB,而JSB底層使用的是cocos2d-x,當代碼運行時,就存在了兩套運行環境--JS運行環境和Cocos2d-x
的鏡像運行環境。項目的代碼在JS運行環境中每添加一個節點,cocos2d-x中就會相應的添加一個相同的節點,可是這兩個運行環境是不徹底
相同的,好比說內存管理機制:JS使用JS本身的垃圾回收機制,而cocos2d-x使用的是cocos2d-x本身的一套內存管理機制--智能指針的變種:
計數器機制(不是上方的引用計數)
cocos2d-x爲幾乎全部的類添加了一個基類Ref類,這個類只有一個做用:管理cocos對象的計數,retain()計數加一,release()計數減一
若計數爲零,則自動釋放該對象(緣由以後解釋)
而支持cocos2d-x自動內存管理的類(Node、Action等)都存在一個方法Create(),這個Create中有兩個要關注的點:new與autorelease();
在使用create時,會使用new一個對象,而且計數設爲1(retain()),而後會調用autorelease(顧名思義會自動釋放該對象,計數減一);
如今來看看autorelease,它會將對象放入AutoreleasePool池中,有一個AutoreleaseManger來管理AutoreleasePool,在每一幀結束的
時候,AutoreleasePool中的對象會調用release,若計數爲0,則會內釋放,這樣就實現了cocos2d-x的內存自動回收機制。
3、形成錯誤的緣由
舉個栗子:
let ball = new cc.Sprite(""); this.scheduleOnce(function(){ this.addChind(ball); }.bind(this),2);
這段代碼在瀏覽器上時沒有問題的,可是打包到手機上,就會出錯。緣由很簡單,new以後並無立刻addChind,這時候計數爲一,一幀以後被清除,2s以後再去添加
就會找不到該對象。
這時候能夠改爲下面的代碼
let ball = new cc.Sprite(""); ball.retain(); //計數加一 this.scheduleOnce(function(){ this.addChind(ball); ball.release() //計數減一 }.bind(this),2);