[SOLVED] Every button with the same script fires even though I'm only pressing one

Hi! I’m coming from Unity and getting a little lost while learning PlayCanvas UI and scripting, so I figured I’d post to see what I’m doing wrong. I’m a fairly experienced C# user but not a very experienced JavaScript user.

I’m building a little Nintendo-controller-style ‘d-pad’ out of UI buttons to make it possible to move the player character on a mobile device. I’ve got four buttons: up, down, left, and right.

In Unity, I’d build this by writing one script to move the player in a direction (i.e. a vector3), attaching that same script to each of the four buttons, and then setting that direction value in the inspector for each button. This way I have a nice, simple little reusable script! In PlayCanvas when I try to do the same, the player moves in every button’s direction value at the same time. It’s like the scripts are all firing at once (or there’s just one script that fires any time any button is pressed).


GamepadButton.attributes.add("direction", {type: "vec3", default: [0,0,0], title: "Direction to move"});
GamepadButton.attributes.add("player", {type: "entity", default: "", title: "Player"});

var isButtonPressed = false;

// initialize code called once per entity
GamepadButton.prototype.initialize = function(dt) {
    var self = this;
    // console.log(self.player);
    this.entity.element.on('mousedown', this.onPress, this);
    this.entity.element.on('mouseup', this.onRelease, this);
};

GamepadButton.prototype.update = function(dt) {
    if (isButtonPressed) {
        GamepadButton.prototype.move(this.player, this.direction);
    }
};

GamepadButton.prototype.onPress = function (event) {
    self.isButtonPressed = true;
};

GamepadButton.prototype.onRelease = function (event) {
    self.isButtonPressed = false;
};

GamepadButton.prototype.move = function (player, direction) {
    var rb = player.rigidbody;
    rb.applyForce(direction);
};

I figure I could just create one big button input script and have it handle all the directional buttons, or create one separate script per button – and I’d be fine doing that if it’s just how things are done in PlayCanvas – but I’d also like to know why my way of doing things isn’t working, because I have a feeling it’s my understanding of JavaScript and maybe var/prototypes that is failing me here. If I had to make a guess, I’d say that every button is using that same isButtonPressed variable or something like that, and I’d love to know how to make that not happen.

Thanks so much in advance to anyone who can help!

1 Like

I have debugged the code and the issue seems to be in the global variable isButtonPressed. When you add “this” before any variable then it becomes the class variable. You can simply change the name of the local variable which you are calling with “this” i.e. self.isButtonPressed to any other name and it will work fine.

Hi, thanks so much for your help! Unfortunately I don’t totally understand what you’re suggesting. If I remove the global variable, I get an undefined error; if I stop using “self/this” with “isButtonPressed,” I get the exact same behavior in which multiple buttons fire at once. If I stop using “this” with player, I get another undefined error. Could you post an example of exactly what you mean?

For now I’m going to switch to using one script for all of the button behavior – I don’t think my JavaScript is fluent enough yet to debug this.

1 Like

Hey, check this project on which I added your script and 3 btns. It works fine here.
https://playcanvas.com/editor/scene/1034766

Hi again! Yes, it works, but the buttons aren’t doing different things. I need the buttons to do different actions based on Vector3s defined in the inspector, and that’s where I’m running into problems.

Update: I ended up putting all of the button behavior into one script, and now it works perfectly. It’s actually a bit neater in the inspector, too, since I don’t need to set each button individually, so I’m pleased with it!

var Gamepad = pc.createScript('gamepad');

Gamepad.attributes.add("leftButton", {type: "entity", default: "", title: "Left Button"});
Gamepad.attributes.add("rightButton", {type: "entity", default: "", title: "Right Button"});
Gamepad.attributes.add("upButton", {type: "entity", default: "", title: "Up Button"});
Gamepad.attributes.add("downButton", {type: "entity", default: "", title: "Down Button"});

Gamepad.attributes.add("leftDirection", {type: "vec3", default: [0,0,0], title: "Direction to move left"});
Gamepad.attributes.add("rightDirection", {type: "vec3", default: [0,0,0], title: "Direction to move right"});
Gamepad.attributes.add("upDirection", {type: "vec3", default: [0,0,0], title: "Direction to move up"});
Gamepad.attributes.add("downDirection", {type: "vec3", default: [0,0,0], title: "Direction to move down"});

Gamepad.attributes.add("player", {type: "entity", default: "", title: "Player"});

var isLeftButtonPressed = false;
var isRightButtonPressed = false;
var isUpButtonPressed = false;
var isDownButtonPressed = false;

// initialize code called once per entity
Gamepad.prototype.initialize = function() {
    
    this.leftButton.element.on('mousedown', this.onLeftPress, this);
    this.leftButton.element.on('mouseup', this.onLeftRelease, this);
    
    this.rightButton.element.on('mousedown', this.onRightPress, this);
    this.rightButton.element.on('mouseup', this.onRightRelease, this);
    
    this.upButton.element.on('mousedown', this.onUpPress, this);
    this.upButton.element.on('mouseup', this.onUpRelease, this);
    
    this.downButton.element.on('mousedown', this.onDownPress, this);
    this.downButton.element.on('mouseup', this.onDownRelease, this);
};

// update code called every frame
Gamepad.prototype.update = function(dt) {
    var rb = this.player.rigidbody;
    
    if (isLeftButtonPressed) {
        rb.applyForce(this.leftDirection);
    }
    if (isRightButtonPressed) {
        rb.applyForce(this.rightDirection);
    }
    if (isUpButtonPressed) {
        rb.applyForce(this.upDirection);
    }
    if (isDownButtonPressed) {
        rb.applyForce(this.downDirection);
    }
};


Gamepad.prototype.onLeftPress = function (event) {
    isLeftButtonPressed = true;
};
Gamepad.prototype.onLeftRelease = function (event) {
    isLeftButtonPressed = false;
};

Gamepad.prototype.onRightPress = function (event) {
    isRightButtonPressed = true;
};
Gamepad.prototype.onRightRelease = function (event) {
    isRightButtonPressed = false;
};

Gamepad.prototype.onUpPress = function (event) {
    isUpButtonPressed = true;
};
Gamepad.prototype.onUpRelease = function (event) {
    isUpButtonPressed = false;
};

Gamepad.prototype.onDownPress = function (event) {
    isDownButtonPressed = true;
};
Gamepad.prototype.onDownRelease = function (event) {
    isDownButtonPressed = false;
};
1 Like