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