☑ Help with app.fire and app.on (PlayCanvas Newbie)

Hi everyone!

I’ve been playing with PlayCanvas for a few days now, but am trying to grasp the flow of how things work, coming from a Flash Actionscript 3 background.

I am trying to get app.fire and app.on to work in a test project of mine, but I just can’t seem to get it working. I’ve got a box on the screen called “Box” with a script attached to it called box.js. Then I’ve got another script called game.js. I’m trying to control the box from game.js, just so I can understand how events work between scripts. I have tried following the tutorials and a couple of posts I found in the forums regarding this, but no luck.

My code is below and the link to my project is:

https://playcanvas.com/project/451215/overview/tutorial-project

Hopefully I shared that correctly. Can anyone tell me what the heck I’m doing wrong? Thanks! :slight_smile:

game.js:

var Game = pc.createScript(‘game’);

Game.prototype.initialize = function() {

this.app.fire("game:moveBox");

};

Game.prototype.update = function(dt) {

};

box.js:

var Box = pc.createScript(‘box’);
var move_box = false;

Box.prototype.initialize = function() {

var onBoxMove = function() {
    this.move_box = true;
};

this.app.on('game:moveBox', onBoxMove);

};

Box.prototype.update = function(dt) {
if (move_box) {
this.entity.translateLocal(0.1, 0, 0);
}
};

There are quite a few things going on here so I go through them as much as I can.

  1. game.js script was not added to any entity in the scene so the code never runs.
  2. As you put both the event callback and the event fire in the initialize() functions of the scripts, the order execution matters and you may have the event fire called before the callback has been initialized(). In this example, you should call the event fire in the postInitialize() function which gets called after initialize(). That way the callback is guaranteed to be setup before the event is fired.
  3. You had move_box as a global variable which is fine but I think you have intended it be to scoped to the instance of the class. With that comes the use of a lexical closure as well.
// initialize code called once per entity
Box.prototype.initialize = function() {
    this.move_box = false;
    
    var self = this;
    
    var onBoxMove = function() {
        self.move_box = true;
    };

    // listen for the player:move event
    this.app.on('game:moveBox', onBoxMove);   
};

Alternatively, you can also do the callback like this:

// initialize code called once per entity
Box.prototype.initialize = function() {
    this.move_box = false;

    // listen for the player:move event
    this.app.on('game:moveBox', this.onBoxMove, this);   
};

Box.prototype.onBoxMove = function() {
    this.move_box = true;
};

Put it all together and it will look like this: https://playcanvas.com/editor/scene/490056

1 Like

This is terrific, thanks so much for the detailed reply and fixed project! I forked your version over so feel free to delete it on your end.

Before editing, I had asked what entity game.js was attached to because I couldn’t find it, but then I saw it was attached to root. Edited to remove that question.

Thanks again, this will really help me get around the nuances of PlayCanvas. There are a lot of gotchas I’m expecting to encounter, but will take it one step at a time. :slight_smile: Hopefully one day I will be able to help people like you helped me, which I fully intend to do once I get the hang of things!

2 Likes

As another tip, if you want to find out what entities are using a particular asset, you can right click on the asset in the asset panel and go to ‘References’.

1 Like

Awesome, thanks so much!

1 Like

looks great

if you also need argument passed use this

In A script :
var paras = "Hello, PlayCanvas !"
this.app.fire('event-name', arg);

In B script:
this.app.on('event-name', foo, this);
var foo = function(some-args) {
alert(some-args);
};

as shown here

1 Like