Initializing other properties

It’s possible you want to change other properties of the prefab instance, in dependence of the values of the user properties. For example, if the flameType property value is "fire", then you set the mass of the body to 50. Because the property values are not set in the constructor, you can listen to the scene-awake event and setup the body properties:

class Dragon extends Phaser.GameObjects.Sprite {

    constructor(scene,...) {
        ...

        /* START-USER-CTR-CODE */

        scene.events.once("scene-awake", this.awake, this);

        /* END-USER-CTR-CODE */
    }

    /** @type {"fire"|"smoke"|"laser"} */
    flameType = "fire";

    /* START-USER-CODE */

    awake() {

        // at this point, all objects in the scene are created
        // and the user properties are set with new values

        if (this.flameType === "fire") {
            this.body.mass = 50;
        }
    }

    /* END-USER-CODE */
}

If you enable the Generate Awake Handler flag in the Compiler Prefab Settings, the scene compiler will generate this code for you:

Generate awake event handler.
class Level extends Phaser.GameObjects.Image {

    constructor(scene,...) {

        // awake handler
        this.scene.events.once("scene-awake", () => this.awake());

        ...
    }
}

It is your responsibility to write the awake method.

The scene-awake event

The scene-awake event is not part of the Phaser API. It’s a custom event the Scene Editor uses as convention. When the scene compiler generates the code of a scene, it also generates the code for emitting the scene-awake event. This event is emitted just after all objects are created:

class Level extends Phaser.Scene {
...
    editorCreate() {
        ...

        // dragon
        const dragon = new Dragon(this, 370, 218);
        this.add.existing(dragon);

        ...

        // dragon (prefab fields)
        dragon.maxSpeed = 300;
        dragon.flameType = "smoke";
        dragon.onClickHandler = obj => this.selectDragon(obj);
        ...

        this.events.emit("scene-awake");
    }
...
}

As we mentioned in the previous sections, prefabs and user components can listen to this event for reading the values set to the user properties.

It is important that you keep in mind that if you create a dynamic prefab instance, and it requires the scene-awake event, then you should call it manually:

spawnDino(scene, x, y, flame) {

    const dragon = new Dragon(scene, x, y);
    dragon.flameType = flame;
    // send the awake notification to the new object
    scene.events.emit("scene-awake");
}

Because the scene-awake event is listened once in prefabs and user components, only the new objects will be notified.

As alternative to the scene-awake event, you can listen the Phaser.Scenes.Events.UPDATE event. It is emitted by the scene at every tick, so you just need to register the listener to be called once:

scene.events.once("Phaser.Scenes.Events.UPDATE", this.start, this);

Note that if you need to “awake” prefab before the game starts updating, you should listen to the scene-awake event.

The scene-awake event is also used by components, learn more about it.

Using properties with custom definition

You can set a user property with a Custom Definition:

Set custom definition flag.

This means, the scene compiler skips the definition of the property. For example, if you set the flameType as Custom Definition, the flameType property declaration isn’t generated. Instead, a flameType property initialization is included in the constructor:

class Dragon extends Phaser.GameObjects.Sprite {

    constructor(scene,...) {
        ...

        // the compiler adds this
        this.flameType = "fire";
    }

    // the compiler skips this:
    // flameType = "fire";
}

Then, you can write a custom setter and initialize other fields of the prefab:

class Dragon extends Phaser.GameObjects.Sprite {

    constructor(scene,...) {
        ...
        this.flameType = "fire";
    }

    /* START-USER-CODE */

    set flameType(flameType) {

        // update the body with the flameType

        if (flameType === "fire") {
            this.body.mass = 50;
        }
    }

    /* END-USER-CODE */
}

Note that you don’t need to listen for the prefab-awake event anymore. Setting the flameType property will update the prefab state in the expected way. It’s possible you also need to define a getter for the flameType. If that’s the case, you can store its value in a new field, or compute it.