我使用iOS和Android的Cordova编写了一款混合游戏。在某些Android设备上,游戏在几分钟后崩溃,并在屏幕上显示“((应用程序名称)已停止”)消息。在过去的一周中,我一直在尝试查找导致崩溃的原因,但一直无法找到它。我已经对此发起了一个话题,但是今天我观察到了一些值得保证的话题。请允许我首先告诉您有关崩溃的信息,以及为解决该崩溃所做的一切。
游戏使用两个画布。一个不可见且不属于DOM(MAINCanvas)的对象,并且无论实际屏幕大小如何,该对象始终具有固定的大小。所有绘图都在该画布上完成。还有另一个与屏幕大小相同且可见的画布(DISPLAYCanvas)。我在游戏开始时存储了这些画布的上下文:
var MAINCanvas = document.createElement( "canvas" );
var DISPLAYCanvas = document.createElement( "canvas" );
document.body.appendChild(DISPLAYCanvas);
MAINCanvas.context = MAINCanvas.getContext("2d", { alpha: false } );
DISPLAYCanvas.context = DISPLAYCanvas.getContext("2d", { alpha: false } );
我的游戏的主循环如下:
function MainLoop() {
doStuff();
doSomeMoreStuff();
Render(); // This renders all game elements on the invisible MAINCanvas
DISPLAYCanvas.context.drawImage( MAINCanvas, 0, 0 );
window.requestAnimationFrame( MainLoop );
}
几分钟后,游戏每次崩溃。为了弄清楚它崩溃的位置,我添加了一些console.logs:
function MainLoop() {
console.log( "Stuff" );
doStuff();
console.log( "SomeMoreStuff" );
doSomeMoreStuff();
console.log( "Render" );
Render(); // This renders all game elements on the invisible MAINCanvas
console.log( "Draw" );
DISPLAYCanvas.context.drawImage( MAINCanvas, 0, 0 );
window.requestAnimationFrame( MainLoop );
}
事实证明,它在不同的地方崩溃了。
然后我怀疑这可能是罪魁祸首:
MAINCanvas.context = MAINCanvas.getContext("2d", { alpha: false } );
DISPLAYCanvas.context = DISPLAYCanvas.getContext("2d", { alpha: false } );
我正在向DOM对象添加属性,并且我记得在某处读过禁止使用的内容,它可以防止对象的(副本)被垃圾回收。因此,我对此进行了更改:
var MAINContext = MAINCanvas.getContext("2d", { alpha: false } );
var DISPLAYContext = DISPLAYCanvas.getContext("2d", { alpha: false };
我的主循环到:
function MainLoop() {
console.log( "Stuff" );
doStuff();
console.log( "SomeMoreStuff" );
doSomeMoreStuff();
console.log( "Render" );
Render(); // This renders all game elements on the invisible MAINCanvas
console.log( "Draw" );
DISPLAYContext.drawImage( MAINCanvas, 0, 0 );
window.requestAnimationFrame( MainLoop );
}
它不再崩溃了!我很高兴终于在经过7天的令人沮丧的调试后终于找到了崩溃的原因。我现在可以毫无问题地玩游戏了。
因此,为了准备发布游戏,我删除了console.log()行。可以肯定的是,我再次测试了游戏,...在几分钟后崩溃了。因此,我在mainloop中添加了一个console.log:
function MainLoop() {
console.log( "Stuff" );
doStuff();
doSomeMoreStuff();
Render(); // This renders all game elements on the invisible MAINCanvas
DISPLAYContext.drawImage( MAINCanvas, 0, 0 );
window.requestAnimationFrame( MainLoop );
}
再次测试,它没有崩溃。删除了console.log()并使其崩溃。我尝试过几次,每次删除console.log()时,游戏都会崩溃。如果添加,则不会。一致。
我现在唯一想到的就是console.log会触发垃圾回收吗?
答案 0 :(得分:0)
我认为这是 console.log()在生命周期中造成的延迟。
过去也有类似的问题。
尝试将代码包装在延迟为0秒的超时时间内,以使该循环线程化运行。
示例
function MainLoop() {
//console.log("MainLoop start");
doStuff();
doSomeMoreStuff();
Render(); // This renders all game elements on the invisible MAINCanvas
DISPLAYContext.drawImage( MAINCanvas, 0, 0 );
window.setTimeout(function(){
window.requestAnimationFrame( MainLoop );
},0);
}
也许可以尝试一下,并以相同的方式添加其他密集动作。
编辑: 您还可以尝试降低帧速率-也许这些特殊的Android设备没有足够的功能来处理帧速率...
示例
var framesPerSecond = 10;
function MainLoop() {
//console.log("MainLoop start");
doStuff();
doSomeMoreStuff();
Render(); // This renders all game elements on the invisible MAINCanvas
DISPLAYContext.drawImage( MAINCanvas, 0, 0 );
window.setTimeout(function(){
window.requestAnimationFrame( MainLoop );
}, (1000 / framesPerSecond));
}
希望这会有所帮助。
享受!