[SOLVED] A variable this.name does not keep its value

Hi, I have this script:

var Person = pc.createScript('person');

Person.attributes.add('material_happy_0', {type: "asset", assetType: "material"});
Person.attributes.add('material_sad_0', {type: "asset", assetType: "material"});
Person.attributes.add('material_happy_1', {type: "asset", assetType: "material"});
Person.attributes.add('material_sad_1', {type: "asset", assetType: "material"});
Person.attributes.add('material_happy_2', {type: "asset", assetType: "material"});
Person.attributes.add('material_sad_2', {type: "asset", assetType: "material"});
Person.attributes.add('material_happy_3', {type: "asset", assetType: "material"});
Person.attributes.add('material_sad_3', {type: "asset", assetType: "material"});

Person.prototype.onCollision = function(result) {
    var entity = result.other;
    if (entity.script && entity.script.box) {
        // set happy version
        switch (this.mTypeSel) {
            case 0:
                this.entity.render.material = this.material_happy_0.resource;
                break;
            case 1:
                this.entity.render.material = this.material_happy_1.resource;
                break;
            case 2:
                this.entity.render.material = this.material_happy_2.resource;
                break;
            case 3:
                this.entity.render.material = this.material_happy_3.resource;
                break;
        }
    }
};

Person.prototype.setType = function(select) {
    this.mTypeSel = select;
    switch (this.mTypeSel) {
        case 0:
            this.entity.render.material = this.material_sad_0.resource;
            break;
        case 1:
            this.entity.render.material = this.material_sad_1.resource;
            break;
        case 2:
            this.entity.render.material = this.material_sad_2.resource;
            break;
        case 3:
            this.entity.render.material = this.material_sad_3.resource;
            break;
    }
};

// initialize code called once per entity
Person.prototype.initialize = function() {
    this.mTypeSel = 0;
    this.entity.collision.on('collisionstart', this.onCollision, this);
};

After creating each entity of this type I call the setType() function to set this.mTypeSel to one of 4 values and set the material of the entity accordingly.
This all works fine.
But when the entity is hit by a box I want the material to change to a new material depending on this.mTypeSel. The collision is detected and onCollision() is called. But inside this function the value of this.mTypeSel is always 0! So the wrong material is selected.
How is that possible?

I Know setType() is called correctly, because I see the material change.

From a quick glance, I can’t see anything wrong as long as you are calling setType on the script.

Maybe an example project would help here?

1 Like

The strange thing is that it works when I delete the line

this.mTypeSel = 0;

in the initialize function and insert

Person.attributes.add('mTypeSel', {type: 'number', default: 0});

So I gues this is a PlayCanvas bug?

Can’t really tell you without a project to look at

What you’ve done shouldn’t make a difference

My guess is that you’ve called setType on the script before it’s been initialised and the initialisation function is setting the value to 0 after you’ve setType

Are you calling setType from another script’s initialise function? If so, try moving that call to the postInitialize function instead

No, I call setType actually a few seconds after starting the game.
I’m strict in doing only simple initialization in the initialize functions.

I would like to show you the project, but I do not know how.
Please tell me how.

What I do:

  • clone an entity (that is disabled)
  • call the setType of the clone
  • enabled this new clone

will the initialize function be called when the entity is cloned?

Hi @simmania!

You can share an editor link of your project (if it is a public project).

The initialize function of the script that’s on the cloned entity will be called.

Initialize is called when the entity is first enabled.

So in this case, you are calling setType before initialize

There are a couple of ways to get around this:

  1. Use the attributes like you did before
  2. Call setType after enabling the Entity
  3. In initialize, chexk if this.mTypeSel is undefined before setting it to 0

Yes, that was the problem! I assumed the initialize would be called when the object is constructed. (I’m used to C++ and related it to a constructor). But Now I understand that the initialize is called when enabled.