AndEngineのSoundの罠

どうも、現在ゲームを3つ並行製作しております俺です。
自分でやっといて頭がおかしくなりそうです。
時間とアイディア、デザインをまとめる腕が欲しい。

ゲームにはなるべくBGMやサウンドがあった方がいいというのは
身に沁みて分かりましたが、
AndEngineのSoundにちょっとした面倒なアレがあるのに気付きました。









「普通に」AndEngineを使ってる人は以降の記述は時間の無駄です。
普通というのは、アクティビティでもう全てのサウンドを読んでおき、
それを時と場所に応じて使っている人です。


こちら、俺が2013に買って
知識ゼロの状態からゲームを作れるまでに至れたお世話になった本でございます。

AndEngineでつくるAndroid 2Dゲーム (SMART GAME DEVELOPER)AndEngineでつくるAndroid 2Dゲーム (SMART GAME DEVELOPER)
(2012/12/14)
立花 翔

商品詳細を見る


アフィじゃないよ。
AndEngineはさほど日本で浸透しておらず、
調べてもヒットするのは9割が海外フォーラムです。
そんな中日本語の書籍でちゃんとまとめてあるのは唯一この本だけ!というナイスな一冊。
開発環境の導入から何から記述してあるのでこれからやってみようって人にもお勧めです。


が!
よそ様のサイトでも指摘されているとおり、
この本の記述どおりにやるとメモリリークを起こす箇所があったり、
関数やクラスの使い方が間違っている箇所があります。
別にちょっとしたゲームを作るくらいなら何の問題もありません。
現にこの本で紹介しているゲームの作り方3つのサンプルはちょっとしたゲームですから。



しかし、シーン切り替えが多かったり結構長めにやるゲームだと
エラーが出てしまって困ります。
ちなみに自分が最初の方に出した「焼却処分場」「実績解除君」「30秒モンスタントラボ」
あたりはこの本の通りにやっているため長時間遊ぶと確実にエラーを吐きます。


ResourceUtilのメモリリークはよそ様のサイトを見れば解決するとして、
問題はSoundです。ついでに言えば、Musicも。


この本では、シーンクラスが生成された時に
サウンドやBGMを読み込む処理を行っています。
これ自体は間違いではないのですが、
双方開放を行っていません。

Musicを解放する際は、シーン終了時に
getBaseActivity().getMusicManager().releaseAll();
を行ってください。
でないといずれメモリが足りなくなりBGMが止まります。


Musicの方はこれでいいのですが、Soundの方はそうは問屋が卸しませんでした。
よーしMusicと同じノリで
getBaseActivity().getSoundManager().releaseAll();
をやるぞーってやると
以降一切音が鳴らなくなります。

なぜかというと、これは前述の「普通に使っている」人向けの処理であり、
SoundManagerが保持しているSoundPool(渡されたサウンドを格納しているプール)をreleaseしています。
SoundPoolがreleaseされるとどうなるかというとそのプールは機能を停止します
AndEngine側としては「もうサウンド使わないよって時に使ってね!」って用意した関数なので
シーン切り替えの解放で行ってしまうと以降使えなくなってしまうのです。



じゃ本でも特に何もしてないし問題ないんじゃね?
ってことで放っておくと、しばらくしてから問題が起きます。
あの本に載っているアプリは、シーン遷移が非常に少ないもの、
ゲームプレイ時間が短いものです。
つまり、基本的にはエラーを吐く前にユーザーがプレイを終了します。

ユーザーがプレイをすぐ終えないゲームでこの問題を放置し続けるとどうなるかというと
音が鳴らなくなります。またかよ!

なぜかと申せば、まぁログを見ていれば察しはつくのですが
「257番目のサウンドが読み込めないよ!もう音鳴らせないよ!(意訳)」
と喚き立てられます。
SoundPoolさんは、サウンドを256個までしか読み込めません。
5個Soundを使用しているシーンを50回ほどリトライすると、このエラーを吐きます。

NinjaRunとか50回もリトライする前に終わるでしょうから、
このエラーには誰も気付くことなくプログラムが終了します。

SoundPoolは入ってるサウンドを1つずつ消してまっさらにすることができないようなので、
リセットのためにはReleaseしなければいけません。
指定IDのサウンドをアンロードする処理はありますが、
例えばID:2のサウンドを消したところで
次に読み込むサウンドのIDは3になっていしまいます。2には入りません。
入れては消してを繰り返しても、256回やったらエラーを吐きます。
releaseすれば0には戻せますが、それは機能停止を意味します。



じゃどないすんねん!ってことになりますが、
上の本を使ってゲームを作ってる人は
「Soundクラスを使うな」ということになります。
シーンごとにSoundPoolを包括したクラスを自作して使えばいいんです。



急拵えなのでもっと美しく、簡素に、便利に作れるでしょうが
今は一旦この形で使用してます。
落ち着いたらもっと使いやすくします。





public class MySoundPool {

   private SoundPool sp;
   private int soundnum;

   public AssetFileDescriptor[] afd;

   public MySoundPool(int sn){
       soundnum = sn;
       sp = new SoundPool(soundnum,AudioManager.STREAM_MUSIC,0);

       afd = new AssetFileDescriptor[soundnum];
   }


   public void load(MultiSceneActivity ma,String[] s){

        AssetManager am = ma.getResources().getAssets();

        for(int i=0;i<soundnum;i++){
           try{
              afd[i] = am.openFd("sfx/"+s[i]);
           }catch (IOException e) {
              e.printStackTrace();
           }
        }

        for(int i=0;i<soundnum;i++){
           sp.load(afd[i], 1);
        }
   }


   public void play(int n){
       sp.play(n,1,1,0, 0,1);
   }


   public void release(){

       for(int i=0;i<soundnum;i++){
          sp.unload(i+1);
       }
       sp.release();
   }

}



なにぶんプログラムは何も知らない人よりはできる程度のなので依然素人です。
故に間違いや他に便利な方法があるかもしれないことをご了承ください。


まず、こいつを使うシーンで
private MySoundPool msp;
とでもやっておき、然るべき箇所でnewします。
引数は使うサウンドの数です。

初期化したら、サウンドをロードします。
第一引数にはMultiSceneActivityを渡しやってください。
第二は、サウンドの名前です。
面倒なので、ここではString配列にぶっ込んでます。
String[] s = new String[3];
s[0] = "hina.wav";;
s[1] = "chan.wav";
s[2] = "curry.wav":
msp.load(getBaseActivity,s);
って感じです。
サウンドを勝手にロードします。


再生するときはplay関数です。
さっきぶっ込んだサウンドの番号を入れます。
IDで指定するので0は1になります。
ややこしいんでplay側で+1してもいいです。

ほんとは文字列指定とかしたいんであとで改良します。


で、シーンが終わったらrelease関数を使ってください。
これで円満解決です。
いまのところ、音楽が止まったりサウンドが停止したりということは起きなくなりました。

AndEngine絡みで困っても海外フォーラムを頼るか、探してもないかで
最終的に自力でなんとかするしかないかって感じなのでつらいです。ライツーです。



サウンドとは全く関係ないですが
LineとSpriteの当たり判定が関数で取れることが分かってちょっと興奮してます。
これでゲーム作りたいところです。っていうかもう作ってます。

テーマ : ゲーム製作 関連
ジャンル : ゲーム

コメントの投稿

Secret

プロフィール

いすぃ

Author:いすぃ
ゲームを作ってたりゲームしてたり何もしてなかったりしてます

お仕事あれば請け負います。
ゲーム作ってみたい!とか初歩からプログラムやってみたい!って人もご一報ください。

ゲーム面白かったよ!
今後も応援するよ!などなどの意味で下記から心ばかりの支援をしていただけると本当に助かります。
Enty


twitter
ニコニココミュ
pixiv

最新記事
カテゴリ
最新コメント
最新トラックバック
月別アーカイブ
kaunta-
検索フォーム
リンク
スポンサードリンク