template-react icon indicating copy to clipboard operation
template-react copied to clipboard

Plugins getting destroyed on game create and hot reload

Open KlutzyBubbles opened this issue 10 months ago • 5 comments

I have been trying to use a plugin with this template but it just gets destroyed, minimal example can be found at https://github.com/KlutzyBubbles/phaser-react-plugin

However is only gets destroyed when a browser refresh or hot reload of phaser related files happens, but works fine when react files are hot reloaded.

Below is an image where 1 is a browser refresh, 2 is a hot reload from a react file and 3 is a hot reload from a scene file.

Image

The only spot i can see the game being destroyed which could trigger the plugin destroying is https://github.com/phaserjs/template-react/blob/db8c134eb6328ba5d08eb4ef77270f38e2e0b9b9/src/game/PhaserGame.jsx#L11C4-L32C15 but i don't know what to do to fix it. Any help or pointers would be greatly appreciated.

This can also be replicated in the typescript version of this template

KlutzyBubbles avatar Apr 16 '25 00:04 KlutzyBubbles

There seem to be an issue with the template indeed. Your plugin is stored inside the PluginCache manager that is global to the page, since the Game.destroy() method is an async process (it waits for the next animation frame), the PluginCache is cleaned after the second game is started.

If we log it before the new game creation:

const StartGame = (parent) => {
    console.log(Phaser.Plugins.PluginCache.getCustom("ExamplePlugin"));

    return new Phaser.Game({ ...config, parent });
};

We can see that it is undefinedwhen the first game is created, but it is already instantiated when the second game is created.

[vite] connecting... client:495:9
[vite] connected. client:614:15
Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools react-dom_client.js:21551:25
undefined main.js:36:13
Un AudioContext n’a pas pu démarrer automatiquement. Il doit être créé ou repris après un geste de l’utilisateur sur la page. phaser.js:116368:30
     Phaser v3.88.2 (WebGL | Web Audio)  https://phaser.io/v388 phaser.js:8456:33
ExamplePlugin init ExamplePlugin.js:12:17
ExamplePlugin start ExamplePlugin.js:17:17
Object { plugin: class ExamplePlugin, mapping: null, data: null }
main.js:36:13
Un AudioContext n’a pas pu démarrer automatiquement. Il doit être créé ou repris après un geste de l’utilisateur sur la page. phaser.js:116368:30
     Phaser v3.88.2 (WebGL | Web Audio)  https://phaser.io/v388 phaser.js:8456:33
Plugin key in use: ExamplePlugin phaser.js:95031:31
ExamplePlugin destroy ExamplePlugin.js:27:17
Un AudioContext n’a pas pu démarrer automatiquement. Il doit être créé ou repris après un geste de l’utilisateur sur la page. phaser.js:116343:33

Note that the double game rendering is visible as well if the animation frame is slowed down a bit:

Image

raaaahman avatar Apr 17 '25 13:04 raaaahman

Yes, the problem is because of the strict React mode.

In the file: PhaserGame.jsx you could comment out the lines responsible for destroying the Game:

        return () => {

            if (game.current)
            {
                // game.current.destroy(true);
                // game.current = undefined;
            }

        }

gammafp avatar Apr 24 '25 13:04 gammafp

Yes, the problem is because of the strict React mode.

In the file: PhaserGame.jsx you could comment out the lines responsible for destroying the Game:

    return () => {

        if (game.current)
        {
            // game.current.destroy(true);
            // game.current = undefined;
        }

    }

Would this not leave extra game instances open if the game-container were to be unmounted and then remounted, as the previous game would not be destroyed but another would be created?

I am currently doing this for the time being but with a big comment reminding myself to find a proper fix before actually shipping the game, as i don't want there to be a possibility for multiple game instances to just linger until the process is closed.

KlutzyBubbles avatar Apr 24 '25 14:04 KlutzyBubbles

The references we added at the beginning should prevent multiple instances.

gammafp avatar Apr 24 '25 15:04 gammafp

The issue is that destroying the game is not a synchronous process, since it needs to wait on the next animation frame from the browser. So the double canvas may happen if this animation frame is slow.

raaaahman avatar May 02 '25 09:05 raaaahman