Invalid Scene Plugin: UIPlugin

I’m doing my first game with Phaser, which it’s an awesome library!

However, I’m facing a problem while trying to add a plugin to a scene (not globally). This is my current project structure:

- myGame
    - assets/
    - plugins/
        - ui/
            - (more plugin directories) ...
            - index.js
            - ui-plugin.js
    - scenes/
        - main.js
        - game.js
        - ranking.js
    - app.html
    - app.js

In app.js I create the game instance with let game = new Phaser.Game(config);. I load the different scenes of my game inside the config object with the scene property set to [Main, Game, Ranking]. This works OK.

My main.js and game.js follow the below structure:

class Game extends Phaser.Scene {
    constructor() {
        super({
            key: 'game'
        });
    }
    
    preload() {}
    create() {}
    update() {}
}

But when I’m in Ranking scene I can’t wonder how to load a plugin. Specifically, this plugin by Rex. I have read the documentation and seen the examples in the Phaser 3 labs. This is my Ranking class.

class Ranking extends Phaser.Scene {
    constructor() {
        super({
            key: 'ranking'
        });
    }
    
    preload() {
        this.load.scenePlugin({
            key: 'UIPlugin',
            url: '../plugins/ui/ui-plugin.js',
            sceneKey: 'ui'
    });
    }
    create() {}
    update() {}
}

But when I lunch this, I get this warning: Invalid Scene Plugin: UIPlugin.

And the more I read the plugin documentation and examples the more I get confused because of the different ways of loading plugins (with an import statement, without it, with this.load.scenePlugin(), with this.load.plugin() with the plugins.scene property inside the game configuration, etc).

I’m quite lost. Could someone throw some light on this?

I would do it with an import statement and inside the game configuration. Then you should find your plugin here game.plugins.scenePlugins and you can access use it via scene.ui.something

import UIPlugin from '../plugins/ui/ui-plugin.js'

const config = {
  // ...
  plugins: {
    scene: [
      {
        key: 'UIPlugin',
        plugin: UIPlugin,
        mapping: 'ui'
      }
    ]
  }
  // ...
}

let game = new Phaser.Game(config)
console.log(game.plugins.scenePlugins)

Thanks for your anwer. However, some doubts arised:

  • That way, is the plugin available globally or only for my Ranking scene (which is what I want)? I don’t see any reference to my Ranking scene inside the plugins property…

  • Where do yo put the import statement? I tried to put it in app.js but I get the following error: SyntaxError: import declarations may only appear at top level of a module.

Maybe is the order in which I load my scripts in the HTML important? I attach it here just in case I’m doing something wrong:

<html>

<head>
    <meta charset='utf-8'>
    <title>My Game</title>
    <script src="https://cdn.jsdelivr.net/npm/phaser@3.15/dist/phaser.min.js"></script>
</head>

<body>
    <script src="scenes/main.js"></script>
    <script src="scenes/game.js"></script>
    <script src="scenes/ranking.js"></script>
    <script src="app.js"></script>
</body>

</html>

I see. If you do not use a module bundler like webpack, you can’t use the import statement. Instead you would have to import the ui-pligin.js and all its dependencies in your app.html.

A much easier and better way would be using a webpack based starter template like mine phaser-project-template-es6. It will automatically bundle and optimize all your files and add them to the index.html for you.

Hope this helps :slight_smile:

1 Like

@yannick thank you! It took me a little time to get it work fine but finally I could solve my problem. I add it here what I did just in case someone finds it useful. My final project structure is this:

├── dist
│   └── index.html
├── firebase.json
├── package.json
├── src
│   ├── app.js
│   ├── assets
│   │   └── .jpg, .png files...
│   ├── gameService.js
│   ├── loginService.js
│   └── scenes
│       ├── game.js
│       ├── main.js
│       └── ranking.js
└── webpack.config.js

Using NPM I installed webpack, file-loader, Phaser, phaser3-rex-plugins, etc. (indeed, you can see from my project structure that I no longer save the plugin files locally). My webpack configuration is the below:

const path = require('path');

module.exports = {
    mode: "development",
    entry: './src/app.js',
    output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
       {
         test: /\.(png|jpg)$/,
         use: [
           'file-loader'
         ]
       }
      ]
    }
};

Now, I can import the plugin in app.js like you suggested:

import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin.js";

and add it to the game config.

I can also import assets like images using the file-loader in webpack and use them wherever they are needed.

The last thing left is to run webpack from the terminal and access /dist/index.html in the browser.

1 Like