項目總結之音效播放問題,項目總結音效
項目總結之音效播放問題
DionysosLai(906391500@qq.com) 2014/12/25
Cocos2dx使用的是一個比較簡單、粗糙的語音系統,從語音系統名字SimpleAudioEngine,即可看出來這個系統本身沒有多大的複雜難度,因此使用音效系統時,會有一些比較隱晦的細節,需要我們在開發時特別注意。
語音和音效的區別
一般來說,在cocos2dx中,只用兩種聲音通道模式,一個backmuscic,另一個是effectmusic。前者用來播放背景音樂,後者一般用來播放音效。背景音和音效的區別在於前者比較大,後者比較小。同時背景音提供檢測是否播放完畢功能,而音效沒有。如果,在遊戲中,需要另外檢測聲音播放問題,則只能自己修改引擎代碼,添加一個語音通道。在我們公司開發項目中,由於遊戲要時刻檢測聲音播放問題,因此添加了一個名為voice通道,用來專門播放人物聲音。
另一方面,在預先載入方面,背景音不需要預先載入,只有音效才需要預先載入。同時如果預先載入兩個背景音,前一個背景音記憶體會自動拋棄掉,這個問題在音效方面則沒有。
音效預先載入問題
音效是肯定會載入到記憶體中的,及時未使用preLoadEffect介面預先載入音效,在我們第一次播放音效時,同樣會將該音效載入載入到記憶體中,然後再播放該音效。這也就是為什麼有時候遊戲第一次音效沒有播放出來,或者第一次播放音效時,遊戲明顯卡頓一下。
但另一方面,預先載入音效是會消耗一定時間的,不可一次性載入過多。一般是進入該情境,才將該情境音效載入進來。退出該情境時,可將音效記憶體釋放。
同時,在載入音效時,或者沒有載入音效時,在播放該音效的瞬間,遊戲進入後台,十分有可能將系統掛掉,重啟。這是一個必然的bug。這個問題,引起的原因,應該是在載入音效過程中,執行了pauseAllEffects。相信大家appDelegate代碼均如下:
// This function will be called when the app is inactive. When comes a phone call,it's be invoked toovoid AppDelegate::applicationDidEnterBackground() { CCDirector::sharedDirector()->stopAnimation(); // if you use SimpleAudioEngine, it must be pause SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();SimpleAudioEngine::sharedEngine()->pauseVoice();SimpleAudioEngine::sharedEngine()->pauseAllEffects();}// this function will be called when the app is active againvoid AppDelegate::applicationWillEnterForeground() { CCDirector::sharedDirector()->startAnimation(); // if you use SimpleAudioEngine, it must resume here SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();SimpleAudioEngine::sharedEngine()->resumeVoice();SimpleAudioEngine::sharedEngine()->resumeAllEffects();}
這個問題,基本不可避免,或者目前無力解決這個問題,只能是盡量避免。
迴圈音效播放問題
有時候,有些音效需要迴圈播放。迴圈播放音效時,在PC端會引起各種各樣的問題,例如不能及時關閉,遊戲退到後台,又進入前台,以前暫停過的迴圈音效,又會重新播放,因此迴圈音效調試,一定要在移動端。
迴圈音效的播放,有時候會播放不出來,這個問題很奇怪,一般來說,如果要播放迴圈音效,該音效的大小,最好在40k以內。
另一方面迴圈音效需要記錄該音效的播放ID值,在win32端,改音效ID值是根據音效路徑pszFilePath計算得到,因此第一次播放A音效,第二次播放A音效,前後得到的ID值是一樣的。而在移動端,每次播放音效,ID值都會自增+1,同時如果不預先載入音效,第一次得到的音效ID值為0,這個很重要。這點,可以參考文章:http://post.justbilt.com/2013/11/28/cocos2dx_loop_sound/, 裡面講的細緻到位。
播放多個音效問題
同時播放多個音效時,遊戲會卡頓,及時時播放同一個音效,如果同時播放多個,會明顯感覺遊戲卡頓,而且音效不是一起播放的,會有明顯的前後間隔。因此,避免同時播放多個音效,這也是為什麼我曾在三消遊戲中,不提倡使用每個物品消除都多一個音效問題,而是根據物品個數播放音效。比方消除物品數在3以下,播放A音效,消除物品數超過多少,播放B音效等。能夠要求提供不同種類音效,是程式設計的一個要求。
音效資源釋放問題
一般來說,遊戲退出,結束整個程式,系統會將遊戲記憶體釋放掉。但是,對於聲音記憶體,系統並不釋放,需要我們主動釋放,這裡只需要在遊戲退出時,添加一個簡單的介面:CocosDenshion::SimpleAudioEngine::end();即可。很神奇吧,我也覺得。