- 精通Cocos2d-x游戲開發(進階卷)
- 王永寶
- 759字
- 2020-11-28 22:37:03
6.3 高效播放CSB動畫
在使用CSLoader加載的節點時,可以讓其執行一個ActionTimeline類型的Action,通過調用ActionTimeline的方法可以控制動畫的播放和暫停等,一般情況下要播放一個CSB節點的動畫時,都是先創建CSB文件對應的ActionTimeline,然后讓CSB節點執行,最后調用ActionTimeline的play()方法播放動畫。實際上這是一種低效的做法,因為CSB節點的ActionTimeline是不會停止的,也就是說我們只需要一個ActionTimeline就夠了,而不是每播放一次動畫創建一個。那么應該如何獲取到CSB節點當前的ActionTimeline呢?ActionTimeline與其他的Action有兩點最大的不同,除了ActionTimeline不會停止之外,ActionTimeline在執行的時候,Action的tag就會被設置為節點的tag。
所以正確的做法應該是這樣的,先根據CSB節點的tag獲取Action,并動態轉換成ActionTimeline(在一些舊版本的引擎中,同一個CSB文件創建出來的多個節點對象的ActionTimeline對象是同一個,所以可能出現播放一個ActionTimeline的動畫,所有CSB對象都執行了動畫,可以升級引擎或使用ActionTimeline的clone方法解決),如果轉換成功則使用這個ActionTimeline來播放動畫,否則再使用CSB的路徑創建一個ActionTimeline,讓CSB節點執行這個Action。但如果在運行之后修改了CSB節點的Tag,或者將這個Action停止了,就無法正確播放動畫了。
Cocos2d-x 3.10之前的版本是會自動執行ActionTimeline的,但由于在某些情況下會存在嚴重的內存泄漏,所以Cocos2d-x 3.10的代碼中取消了根節點自動播放ActionTimeline的功能,但嵌套的CSB節點還是會自動播放ActionTimeline。CSLoader的內存泄漏很隱蔽,但危害很大,重現這個內存泄漏的BUG很簡單,只需要在一個for循環中不斷調用CSLoader創建節點,然后再直接調用release將創建的節點釋放,就會產生內存泄漏了,如果加載的是比較復雜的CSB節點,更容易重現這個問題。查看程序占用的內存會發現,程序占用了很大的一塊內存。
這個內存泄漏的原因是因為CSB節點在創建的時候自動執行的ActionTimeline,這時候ActionManager會對CSB節點有一個retain操作,增加了它的引用計數,而直接通過autorelease釋放CSB節點,但并不會真正釋放這個CSB節點,因為沒有一個地方讓ActionManager執行release的操作,如果在釋放之前先執行一下CSB節點的cleanup()方法,就可以解決內存泄漏。