UIViewController 以一种奇怪的方式释放我的 Cocos2d 场景
我有一个 Cocos2d 游戏场景,它加载了由 UIViewController 加载的 EAGLView,但是当我退出游戏场景回到 UIKit 菜单时,我的游戏场景正在以一种奇怪的方式被释放。我想如果我纯粹用 Cocos2d 制作游戏而不将其与 UIKit 结合起来,就不会发生这种情况。如果我在 UIViewController 弹出时调用 CCDirector 的暂停,我发现如果我想重新进入游戏场景,UIViewController 将再次加载,并且简单地恢复 CCDirector 将显示带有 OpenGL 错误的空白屏幕。如果尝试 [[CCDirector sharedDirector] runWithScene]
它说如果场景已经在运行,我就无法执行此操作,但是如果我尝试 ReplaceScene,它会说一条 dealloc 消息(对于 CCSprite,不知道是哪一个) ) 被发送到已释放的实例。这是我的一些代码:
- (void)viewDidLoad {
[super viewDidLoad];
glView = [EAGLView viewWithFrame:self.view.bounds
pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
depthFormat:0 // GL_DEPTH_COMPONENT16_OES
];
glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:glView atIndex:0];
[[CCDirector sharedDirector] setOpenGLView:glView];
if (![[CCDirector sharedDirector] runningScene]) {
CCScene *scene = [GameLayer scene];
[[CCDirector sharedDirector] runWithScene:scene];
}
else {
[self.view insertSubview:[[CCDirector sharedDirector] openGLView] atIndex:0];
[[CCDirector sharedDirector] resume]; // Pause is in viewWillDisappear
// If I replace resume with below, I get message sent to deallocated instance
[[CCDirector sharedDirector] replaceScene:scene];
}
}
如果我像这样运行它,我会在 CCTextureAtlas 内得到 EXC_BAD_ACCESS ,与 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*)(start*6*sizeof( indexs_[0])));
如果我在不重新初始化 glview 的情况下运行它,只在第一次初始化,就像if (![[CCDirector sharedDirector]openGLView])初始化
一样,我在-[EAGLView swapBuffers]中得到一个空白屏幕和OpenGL错误0x0506。
我如何保留我的场景而不做一些过于扭曲的事情,或者干净地释放我的场景,以便我可以使用 [[CCDirected shareDirector] runWithScene]
重新加载它?
I have a Cocos2d game scene that loads with an EAGLView loaded by a UIViewController, but when I exit the game scene back to a UIKit Menu, my game scene is being deallocated in a weird way. I think if I made the game purely in Cocos2d without combining it with UIKit, this would not happen. If I call pause on CCDirector when UIViewController pops, I found that if I want to reenter the game scene, the UIViewController will load again, and simply resuming CCDirector will show a blank screen with an OpenGL error. If try [[CCDirector sharedDirector] runWithScene]
it says I cannot do that if a scene is already running, but if I try replaceScene, it says that a dealloc message (for a CCSprite, no idea which one) is being sent to a deallocated instance. Here is some of my code:
- (void)viewDidLoad {
[super viewDidLoad];
glView = [EAGLView viewWithFrame:self.view.bounds
pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
depthFormat:0 // GL_DEPTH_COMPONENT16_OES
];
glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:glView atIndex:0];
[[CCDirector sharedDirector] setOpenGLView:glView];
if (![[CCDirector sharedDirector] runningScene]) {
CCScene *scene = [GameLayer scene];
[[CCDirector sharedDirector] runWithScene:scene];
}
else {
[self.view insertSubview:[[CCDirector sharedDirector] openGLView] atIndex:0];
[[CCDirector sharedDirector] resume]; // Pause is in viewWillDisappear
// If I replace resume with below, I get message sent to deallocated instance
[[CCDirector sharedDirector] replaceScene:scene];
}
}
If I run it like this, I get EXC_BAD_ACCESS inside CCTextureAtlas in the line with glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*)(start*6*sizeof(indices_[0])));
If I run it without reinitializing the glview, only initializing the first time, like if (![[CCDirector sharedDirector]openGLView]) initialize
, I get a blank screen and OpenGL error 0x0506 in -[EAGLView swapBuffers].
How would I either retain my scene without doing something too contorted, or cleanly release my scene so that I may reload it with [[CCDirected sharedDirector] runWithScene]
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如何“退出现场”?这将是更有趣的代码。
以下是我对您发布的代码感到奇怪的地方:
通常,当您运行replaceScene时,您会提供一个新场景。您可能会尝试使用与当前正在运行的场景相同的场景来替换场景。这肯定会让cocos2d崩溃。如果您希望相同的场景重新出现,请不要调用replaceScene 或重新创建场景。
您还需要检查当前运行的场景是否未解除分配。在场景的 dealloc 方法中设置断点。如果它解除分配,您可能会误以为必须从内存中擦除 cocos2d 场景。你不应该这样做,我相信 cocos2d 总是期望在你调用 runWithScene 之后至少有一个正在运行的场景。
就其价值而言,您将需要使用 startAnimation 和 stopAnimation 而不是暂停和恢复。这将完全停止 Cocos2D 而不释放场景,因此它的工作方式与暂停/恢复相同。我的猜测是,它在内部完全关闭了游戏循环,而暂停/恢复使其以非常慢的速度运行,如果我没记错的话,即 4 fps。
我遇到过暂停/恢复会导致“-[EAGLView swapBuffers] 中的 OpenGL 错误 0x0506”的情况,而 startAnimation/stopAnimation 会修复该问题。
How do you "exit the scene"? This would be the more interesting code to have a look at.
Here's what I found strange about the code you posted:
Normally when you run replaceScene you provide a new scene. It's possible that you try to replaceScene with the same scene that is also the currently running scene. This will certainly crash cocos2d. If you want the same scene to re-appear, either don't call replaceScene or create the scene anew.
You also will want to check that the currently running scene does not dealloc. Set a breakpoint in the dealloc method of the scene. If it deallocs you probably fell for the misconception that you have to wipe the cocos2d scene from memory. You should not do that, I believe cocos2d always expects there to be at least one running scene after you called runWithScene.
For what it's worth, you will want to use startAnimation and stopAnimation instead of pause and resume. This will entirely halt Cocos2D without releasing the scene, so it works the same as pause/resume. My guess is that internally it shuts down the game loop altogether whereas pause/resume keeps it running at a very slow rate, ie 4 fps if I remember correctly.
I've had cases where pause/resume would cause the "OpenGL error 0x0506 in -[EAGLView swapBuffers]" and startAnimation/stopAnimation would fix that.
无论您如何离开场景调用,
这都会调用 Director 上的许多方法,并使您能够毫无问题地重新进入场景。
How ever you leave the sene call
This will call a number of methods on the Director and enalbe you to re-enter the scene without problems.