2011-02-09 15 views
1

私は小惑星ゲームを作成しています。私のメインクラスでは、船が発射した弾丸を扱う際にいくつかの問題があります。Flash AS3 - オブジェクトを完全に削除するremoveChild()?

すべての箇条書きは「箇条書き」クラスであり、メインクラスの「弾丸」という配列に格納されています。弾丸が画面を出ると、メインクラスのremoveBullet(bulletID)が呼び出されます。

private function removeBullet(id:int) 
    { 
     removeChild(bullets[id]); 
     bullets.splice(id); 
    } 

私のBulletクラスには、「stillHere」をトレースするenterFrameリスナーがあります。したがって、addChildを使用して箇条書きをメインステージに追加するとすぐに、「stillHere」が出力パネルでポップアップを開始します。

私の問題は、removeBulletを呼び出した後でも、 "stillHere"が出力パネルにポップアップしていて、削除しようとしたオブジェクトがまだメモリのどこかに張り付いているということです。

完全に削除するにはどうすればよいですか?

+0

こんにちは、bullets [id]がBulletインスタンスへの参照を返すことを確認してください。定義されていないかどうかを確認するために弾丸(ID)をトレースしてみてください。 – lomanf

+0

はい、あります。この関数は、弾丸をスクリーンから視覚的にも正常に除去します。 – Lebowski156

+0

オブジェクトプールについて聞いたことがありますか?いくつかの実装を使用する準備ができていますし、この種のもの(弾丸)のために自分で作ることもできます。 – Daniel

答えて

4

あなたはActionScriptを使用しているため、オブジェクトがいつ削除されるかを直接制御することはできません。

本当の問題は、イベントリスナーがまだ発砲していることです。明らかに、removeEventListenerを削除すると呼び出すことで、この問題を解決できます。

より良いアプローチはゲーム全体に対してただ1つのリスナーを持つことです。それは、すべてのゲーム要素(船、小惑星、弾丸、破片など)を個々に進める必要があります。このメソッドは、誤ってイベントリスナーを削除することを忘れてしまったり、要素がタイムステップ内で更新される順序を見ることができるため、コードを明確にします。

public function destroy():void { 
    stop(); // if it's a MovieClip 
    if(parent) parent.removeChild(this); 
} 

は限り私はこの関数を呼び出した後、オブジェクトへの参照を削除して、それは通常、収集しています:

は、私は通常このような何かを読み、私の一時的なオブジェクトでdestroy機能を持っています。

私のコードでは、ほとんどの場合、個々のオブジェクトにリスナーが存在することはほとんどありません。

+0

+1アプリケーション全体に1つのENTER_FRAMEリスナーのみが必要であることを示唆しています。素晴らしいアドバイス。 – scriptocalypse

+1

1年半後、シングルイベントリスナーの良いアドバイスをいただきありがとうございます。私は当時それを得ていなかったが、後見ではこれが最良の選択だっただろう。 – Lebowski156

4

イベントリスナー自体がまだメモリに残っている可能性があります。これは、何かがガベージコレクションされているかどうかをテストする良い方法ではありません。

また、オブジェクトがガベージコレクションされているかどうかを確認する良い方法であっても、コレクションは瞬間的なプロセスではありません。 Flash Playerは、より多くのメモリを割り当てる必要がある場合にのみgcを実行し、そうしない場合はgcを実行しません。

表示リストと箇条書きの配列以外の箇条書きオブジェクトへの他の参照がないと仮定すると、それをガベージコレクションするのに十分です。

EDIT:オブジェクトが収集されているかどうかを観察するためにどのような方法があるのか​​どうかについての質問に答えるために...

あなたは弱い鍵付き辞書でキーとしてオブジェクトを使用することができます。

private var _dict:Dictionary = new Dictionary(true); 
_dict[bullet] = "Bullet is still here..."; 

その後、あなたは弾丸がまだ存在しているかどうかを確認したいとき、ループ内でのキー

for(var key:* in _dict){ 
    trace(key + " " + _dict[key]); 
} 

を反復処理するために...弱い鍵付き辞書のキーは参照としてカウントされませんので、使用ガベージコレクションの目的で、これは機能します。

メモリリークが非常に懸念される場合は、オブジェクトプールを作成してステージから削除した古い箇条書きオブジェクトを配置し、何度も繰り返し使用することを検討するとよいでしょう。このようにすれば、は決してになりますが、すべての箇条書きをガベージコレクションできるようになりますが、限られた数の少数の箇条書き(指定された時間に同時に表示される箇条書きの数) 。これは、弾丸のメモリ占有量が少ない可能性があり、Flashがあなたのゴミを掃除しないようにするためのボーナスを得るため、最適な解決策になるかもしれません。 GCを実行すると、ゴミが取り除かれている間にパフォーマンスが低下するため、その対策によって必要がなくても良いことを防ぐことができます。

+0

追加する場合: 'bullets [id] .removeEventListener(eventListenerName);' 収集されたかどうかを確認する別の方法がありますか? – Lebowski156

+0

私は、削除されるはずのオブジェクトがメインプログラムに影響を与える可能性のある機能を実行し続けることを心配しています。 – Lebowski156

+0

はい、これを行う方法はまったくありません。コメントスペースよりも良いフォーマットが必要なので、私は自分の答えを編集します。 – scriptocalypse

関連する問題