销毁 Phaser.Game 实例的正确方法是什么?

What's the proper way to destroy instance of Phaser.Game?

在创建然后销毁 Phaser.Game 实例的微不足道的情况下,似乎存在内存泄漏。下面是一个完整的工作示例:单击按钮创建一个实例,再次单击将其销毁。重复单击该按钮会导致内存使用量无限制地增长。关于我应该做的移相器生命周期,我是否遗漏了什么?

我将其作为代码片段而不是 jsfiddle 发布,因为您需要查看内存分析器或类似的东西才能看到问题,因此 jsfiddle 只会使问题复杂化。

<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.8.1/phaser.js">
</script>
</head>
<body>
   <button id="button">Click</button>
   <div id="canvas"></div>
   <script>
      window.onload = function() {
         var d, n, game;

         d = document.getElementById('button');
         n = document.getElementById('canvas');

         function preload() {
         }
         function create() {
         }
         function update() {
         }
         function handler() {
            if(game) {
                    game.destroy();
                    game = null;
            } else {
                    game = new Phaser.Game(800, 600, Phaser.AUTO, n, {
                            preload:        preload,
                            create:         create,
                            update:         update
                    });
            }
         }
         d.onclick = handler;
      };
   </script>
</body>
</html>

回答(至少部分)我自己的问题,问题在 Phaser.CanvasPool。每当创建新的 Phaser 实例时,都会创建一个新的 canvas 并将其添加到池中。销毁实例不会从池中删除 canvas 或将其标记为可重复使用。

你可以通过在调用 game.destroy() 之后做一些粗略的事情来解决这个问题,比如设置 Phaser.CanvasPool.pool = [],但是如果你有多个,那将不起作用移相器实例进行中。

如果有人知道正确的工作流程应该是什么,我很想知道---Phaser.CanvasPool 是 Phaser 与 PIXI 的联系点之一,所有这些似乎都没有很好的记录。

编辑:找到内存泄漏的根源。它是 Phaser.Utils.Debug.boot(),它会在每次调用时向池中添加一个新的 canvas,默认情况下是每次创建和启动移相器实例时。

当 enableDebug 启用(默认设置)时,该问题仅影响 WebGL 渲染的 canvases。

为了完整起见,这里是上面代码的编辑版本,它禁用调试,因此不会出现内存泄漏:

<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>test</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.8.1/phaser.js"></script>
</head>
<body>
<button id="button">Click</button>
<div id="canvas"></div>
<script>
window.onload = function() {
    var d, n, game;

    d = document.getElementById('button');
    n = document.getElementById('canvas');

    function preload() {
    }
    function create() {
    }
    function update() {


    }
    function handler() {
            if(game) {
                    game.destroy();
                    game = null;
            } else {
                    game = new Phaser.Game({
                            width:          800,
                            height:         600,
                            renderer:       Phaser.AUTO,
                            parent:         n,
                            enableDebug:    false,
                            state:          {
                                    preload:        preload,
                                    create:         create,
                                    update:         update
                            },
                    });
            }
    }
    d.onclick = handler;
};
</script>
</body>
</html>