Actionscript 3 对象';从内存中删除后重新实例化时,s阶段引用丢失&;显示列表

Actionscript 3 对象';从内存中删除后重新实例化时,s阶段引用丢失&;显示列表,actionscript-3,Actionscript 3,我正在制作一个游戏。当您死亡或赢得某个关卡时,系统会提示您继续或返回主菜单。如果选择进入主菜单,则可以开始新游戏。当你开始一个新游戏时,游戏对象会再次被创建&它的孩子们已经失去了对舞台的参照。我不知道为什么会这样,我花了一个多星期的时间试图找出原因。以下是游戏中的一些代码(以及代码描述),希望能够提供足够的洞察问题发生的原因: 如果在开始菜单上单击“新建游戏”按钮,则会调度NavigationEvent.START事件。完成关卡后,WeeBeeGame将发送LevelEvent.COMPLETE

我正在制作一个游戏。当您死亡或赢得某个关卡时,系统会提示您继续或返回主菜单。如果选择进入主菜单,则可以开始新游戏。当你开始一个新游戏时,游戏对象会再次被创建&它的孩子们已经失去了对舞台的参照。我不知道为什么会这样,我花了一个多星期的时间试图找出原因。以下是游戏中的一些代码(以及代码描述),希望能够提供足够的洞察问题发生的原因:

如果在开始菜单上单击“新建游戏”按钮,则会调度NavigationEvent.START事件。完成关卡后,WeeBeeGame将发送LevelEvent.COMPLETE事件

public class DocumentClass extends MovieClip {

    public var startMenu:StartMenuGenerator = new StartMenuGenerator();
    public var weeBeeGame:WeeBeeGame;
    public var youWonBox:YouWonBox = new YouWonBox();

    public function DocumentClass() {
        // constructor code
        addChild(startMenu);
        startMenu.addEventListener(NavigationEvent.START, startGameHandler);
    }

    public function startGameHandler(e:NavigationEvent) : void {
        this.removeChild(startMenuBG);
        removeChild(startMenu);

        weeBeeGame = new WeeBeeGame();
        this.addChild(weeBeeGame);

        weeBeeGame.addEventListener(LevelEvent.COMPLETE, levelCompleteHandler);
    }

    public function levelCompleteHandler(e:LevelEvent) : void {

        youWonBox.x = this.stage.stageWidth/2;
        youWonBox.y = this.stage.stageHeight/2;
        addChild(youWonBox);

        youWonBox.addEventListener(MouseEvent.CLICK, mouseClickHandler);
    }

    private function mouseClickHandler(e:MouseEvent) : void {
        if(e.target.name === "mainmenubtn"){
            mainmenuHandler();  
        }
    }

    private function continueHandler() : void {
        youWonBox.removeEventListener(MouseEvent.CLICK, mouseClickHandler);
    }

    private function mainmenuHandler() : void {
        youWonBox.removeEventListener(MouseEvent.CLICK, mouseClickHandler);
        WeeBeeGame.collisionDOC.removeChildren();
        removeChild(weeBeeGame);
        weeBeeGame = null;

        this.addChild(startMenuBG);
        addChild(startMenu);
        removeChild(youWonBox);
    }
}
不会显示分派LevelEvent.COMPLETE事件的代码,但它会在级别完成时分派。collisionDOC需要是静态的,因为它在许多其他类中都需要,并保存第三方像素级碰撞检测所需的显示对象

public class WeeBeeGame extends MovieClip {

    public var bee: Bee;
    public var beeHurt:BeeHurt;

    public var spawningDaemon:SpawningDaemon;

    public static var collisionDOC:DisplayObjectContainer;

    public function WeeBeeGame() {
        this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true);
    }

    private function addedToStageHandler(e:Event) : void {
        this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);

        collisionDOC = new MovieClip();
        addChild(collisionDOC);

        bee = new Bee();
        collisionDOC.addChild(bee);

        beeHurt = new BeeHurt(bee.x, bee.y);
        addChild(beeHurt);
        beeHurt.visible = false;

        spawningDaemon = new SpawningDaemon(currentLevel);

        this.addEventListener(LevelEvent.COMPLETE, levelCompleteHandler, false, 0, true);
    }

    private function levelCompleteHandler(e:LevelEvent) : void {
        removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
}
引发1009错误(无法访问null对象引用的属性或方法)的第一行是包含stage.mouseX的行,因为stage引用为null

public class Bee extends MovieClip {

    public function Bee() {
        this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
    }

    private function addedToStageHandler(e:Event) : void {
        this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        this.x = this.stage.stageWidth / 2;
        this.y = this.stage.stageHeight - this.stage.stageHeight / 9;
        this.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 0, true);
    }

    private function enterFrameHandler(e:Event) : void {
        if(stage == null){
            trace('stage is null' + stage.mouseX);
        }
    }
}

当swf第一次打开并创建一个新的WeeBeeGame时,它的子项会引用到该阶段。但是当WeeBeeGame及其子项从显示列表和内存中删除时,它们会丢失引用,即使它们被实例化,它们的引用仍然会丢失。我该如何解决这个问题?我很困惑。谢谢大家

ENTER_FRAME
即使从后台移除显示对象,处理程序也会继续执行。因此,当您
removeChild(weeBeeGame)
那些
ENTER\u FRAME
处理程序仍在尝试访问
stage.mouseX
每个帧时。您需要停止
ENTER_FRAME
处理程序

可能最简单的修复方法是添加
事件。从\u STAGE
处理程序中删除\u以删除
事件。输入\u FRAME
处理程序


更好的修复方法是,不要从游戏对象中添加任何
ENTER\u FRAME
处理程序,而是公开一个公共函数,如
update()
,当游戏运行时,该函数从
WeeBeeGame
中的单个
ENTER\u FRAME
处理程序调用。然后,要完全停止游戏,只需删除单个
ENTER\u FRAME
处理程序即可停止所有更新。这是一种常见的做法。

ENTER\u FRAME
即使从后台删除显示对象,处理程序也会继续执行。因此,当您
removeChild(weeBeeGame)
那些
ENTER\u FRAME
处理程序仍在尝试访问
stage.mouseX
每个帧时。您需要停止
ENTER_FRAME
处理程序

可能最简单的修复方法是添加
事件。从\u STAGE
处理程序中删除\u以删除
事件。输入\u FRAME
处理程序


更好的修复方法是,不要从游戏对象中添加任何
ENTER\u FRAME
处理程序,而是公开一个公共函数,如
update()
,当游戏运行时,该函数从
WeeBeeGame
中的单个
ENTER\u FRAME
处理程序调用。然后,要完全停止游戏,只需删除单个
ENTER\u FRAME
处理程序即可停止所有更新。这是一种常见的做法。

ENTER\u FRAME
即使从后台删除显示对象,处理程序也会继续执行。因此,当您
removeChild(weeBeeGame)
那些
ENTER\u FRAME
处理程序仍在尝试访问
stage.mouseX
每个帧时。您需要停止
ENTER_FRAME
处理程序

可能最简单的修复方法是添加
事件。从\u STAGE
处理程序中删除\u以删除
事件。输入\u FRAME
处理程序


更好的修复方法是,不要从游戏对象中添加任何
ENTER\u FRAME
处理程序,而是公开一个公共函数,如
update()
,当游戏运行时,该函数从
WeeBeeGame
中的单个
ENTER\u FRAME
处理程序调用。然后,要完全停止游戏,只需删除单个
ENTER\u FRAME
处理程序即可停止所有更新。这是一种常见的做法。

ENTER\u FRAME
即使从后台删除显示对象,处理程序也会继续执行。因此,当您
removeChild(weeBeeGame)
那些
ENTER\u FRAME
处理程序仍在尝试访问
stage.mouseX
每个帧时。您需要停止
ENTER_FRAME
处理程序

可能最简单的修复方法是添加
事件。从\u STAGE
处理程序中删除\u以删除
事件。输入\u FRAME
处理程序


更好的修复方法是,不要从游戏对象中添加任何
ENTER\u FRAME
处理程序,而是公开一个公共函数,如
update()
,当游戏运行时,该函数从
WeeBeeGame
中的单个
ENTER\u FRAME
处理程序调用。然后,要完全停止游戏,只需删除单个
ENTER\u FRAME
处理程序即可停止所有更新。这是一种常见做法。

stage
为空时,如何跟踪
stage.mouseX
?它总是会给出一个错误。在
Bee
AddedStatageHandler
中跟踪“Bee added to stage”,查看事件是否真的发生,该阶段是否真的存在,以及它是否发生在错误之前。我打赌
ENTER_FRAME
事件或
spawingdaemon
。感谢回复Andrei。我将
if(stage=null)
部分放在那里,以说明在将对象添加到stage、从stage中删除、从内存中删除、重新实例化然后再次添加到stage之后,stage为null。我在
addedStatageHandler
中跟踪了“bee added to stage”,跟踪语句同时发生在