1

私は小惑星ゲームを作成しています。私のメイン クラスでは、船が発射する弾丸の処理に問題があります。

すべての弾丸は "Bullet" クラスに属し、メイン クラスの "bullets" という配列に格納されます。弾丸が画面から出ると、メイン クラスの removeBullet(bulletID) が呼び出されます。

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

私の Bullet クラスには、「stillHere」をトレースする enterFrame リスナーがあります。そのため、addChild を使用して弾丸がメイン ステージに追加されるとすぐに、出力パネルに「stillHere」が表示され始めます。

私の問題は、removeBullet を呼び出した後でも、出力パネルに「stillHere」が表示され続け、削除しようとしたオブジェクトがまだメモリのどこかに残っていることを示しています。

それを完全に取り除くにはどうすればよいですか?

4

2 に答える 2

4

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

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

表示リストと bullets 配列以外に bullet オブジェクトへの参照がないと仮定すると、ガベージ コレクションを実行するにはこれで十分です。

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

オブジェクトは、キーが弱いディクショナリのキーとして使用できます。

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

次に、弾丸がまだ存在するかどうかを確認したいときはいつでも、 for...in ループを使用してキーを繰り返します

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

弱いキーを持つディクショナリのキーは、ガベージ コレクションの目的では参照としてカウントされないため、これは機能します。

メモリ リークが非常に心配な場合は、ステージから削除した古い弾丸オブジェクトを配置するオブジェクト プールを作成し、それらを繰り返し再利用することを検討してください。このようにして、弾丸がガベージ コレクションされることは決してありませんが、限られた数の弾丸しか作成しない可能性があります (これは、ユーザーが特定の時間に画面上で同時に見る弾丸の数です)。弾丸のメモリ フットプリントが小さい可能性があり、Flash にガベージのクリーンアップを強制しないというボーナスが得られるため、これが最適なソリューションである可能性があります。GC を実行すると、ガベージが削除されている間にパフォーマンスが低下するため、その対策によって、GC が必要になるのを防ぐためにできることを行うことは良いことです。

于 2011-02-09T14:59:15.417 に答える
4

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

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

ただし、より良いアプローチENTER_FRAMEは、ゲーム全体に対して1 つのリスナーのみを使用することです。すべてのゲーム要素 (船、小惑星、弾丸、破片など) を個別に進める必要があります。この方法により、誤ってイベント リスナーを削除するのを忘れる可能性がなくなります。また、時間ステップ内で要素が更新される順序を確認できるため、コードがより明確になります。

私は通常destroy、一時オブジェクトに次のような関数を持っています:

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

この関数を呼び出してからオブジェクトへの参照を削除する限り、通常は収集されます。

このため、私のコードが個々のオブジェクトにリスナーを持つことはめったにありません。

于 2011-02-09T15:20:59.437 に答える