JSON attribute event weirdness

If you have a json attribute like so:

CustomShader.attributes.add('power', {
    type: 'json',
    schema: [{
        name: 'level',
        type: 'number',
        default: 9001,
    }],
});

And code like this:

this.on('attr', this.attributeUpdate, this);
this.power.level *= 50;

Then attributeUpdate will not be called. This makes sense, since the actual attribute wasn’t updated, so we do this and everything is fine again:

var power = this.power;
power.level *= 50;
this.power = power; // will call attributeUpdate.

Still, I was wondering if there was a better way of doing this (something like listening for an event attached to this.power, if that exists.)

I believe there is currently no way to listen on change events of the JSON scheme fields directly. Perhaps a good feature request for Editor?:

Otherwise, you can continue with your current approach, or consider switching to another attribute type. Another option would be to start listening on these attributes manually. However, it is probably not more convenient than your current approach and you would then need to create some convenience script to handle reading/writing to those fields. Nevertheless, here is a barebone variant, which can give you some ideas:

/* jshint esversion: 6 */

class MyScript extends pc.ScriptType {
    
    initialize() {
        this.player = new Observer(this.playerAttributes);
        this.player.on('power:set', this.onPowerChange, this);
    }

    onSomeAction() {
        this.player.set('power', 9001);
    }
    
    onPowerChange(newPower) {
        // this.player.power === 9001
    }

}

pc.registerScript(MyScript, 'myScript');

MyScript.attributes.add('playerAttributes', {
    type: 'json',
    schema: [{
        name: 'power',
        type: 'number',
        default: 1
    }],
});