FindByName Enable / Disable object

I don’t know what I am doing wrong in this code. I have assigned this code to an Entity with a collider on it.

Now when I enter the volume I get this error:
“Uncaught TypeError: Cannot set property ‘enabled’ of undefined”

I also placed a console.log on it to see if the object in the scene is found. And it is found.

var TriggerVolume = pc.createScript('triggerVolume');

// initialize code called once per entity
TriggerVolume.prototype.initialize = function() 
{
    this.TriggerZone = this.app.root.findByName("Zone2");
    
    
    this.entity.collision.on('triggerenter', function (entity) 
        { 
        this.TriggerZone.enabled = false;
        console.log(this.TriggerZone + ' has entered trigger volume.');
        }
    );
    
    this.entity.collision.on('triggerleave', function (entity) 
        {
        console.log(entity.name + ' has left trigger volume.');
        }  
    );
};

Hope someone can help me out.

Best,
Maarten

Hi @Maarten_deVries,

It looks like you’re having problems with scope, so when you are referring to this in your collision event, it is referring to the scope within the collision function. To solve for this, you have two options. The first is to use a self variable that you can reference back to like this:

var TriggerVolume = pc.createScript('triggerVolume');

// initialize code called once per entity
TriggerVolume.prototype.initialize = function() 
{
    var self = this;
    this.TriggerZone = this.app.root.findByName("Zone2");
    
    
    this.entity.collision.on('triggerenter', function (entity) 
        { 
        self.TriggerZone.enabled = false;
        console.log(self.TriggerZone + ' has entered trigger volume.');
        }
    );
    
    this.entity.collision.on('triggerleave', function (entity) 
        {
        console.log(entity.name + ' has left trigger volume.');
        }  
    );
};

The other option is to pass along the context to your collision function like this:

var TriggerVolume = pc.createScript('triggerVolume');

// initialize code called once per entity
TriggerVolume.prototype.initialize = function() 
{
    this.TriggerZone = this.app.root.findByName("Zone2");
    
    
    this.entity.collision.on('triggerenter', function (entity) 
        { 
        this.TriggerZone.enabled = false;
        console.log(this.TriggerZone + ' has entered trigger volume.');
        }, this);
    
    this.entity.collision.on('triggerleave', function (entity) 
        {
        console.log(entity.name + ' has left trigger volume.');
        }, this);
};
1 Like

thank you for the quick reply and clear explanation. I got my script working before I read this reply.
I however did it different then your answer.

var TriggerVolume = pc.createScript('triggerVolume');

// initialize code called once per entity
TriggerVolume.prototype.initialize = function() 
{
    var TriggerZone = this.app.root.findByName("Zone2");
    
    
    this.entity.collision.on('triggerenter', function (entity) 
        { 
            TriggerZone.enabled = false;
            console.log(this.TriggerZone + ' has entered trigger volume.');
        }
    );
    
    this.entity.collision.on('triggerleave', function (entity) 
        {
        console.log(entity.name + ' has left trigger volume.');
        }  
    );
};

Instead of this.TriggerZone = this.app.root.findByName("Zone2");
I did this: var TriggerZone = this.app.root.findByName("Zone2");

and changed this.TriggerZone.enabled = false;
to TriggerZone.enabled = false;

Is this also a correct way?

HI @Maarten_deVries,

That is also a valid solution. The only thing to think about is that using var TriggerZone = this.app.root.findByName("Zone2"); will only be available inside of your initialize function. If you use this.TriggerZone = this.app.root.findByName("Zone2");, It will be available to other top level functions of your scripts, but it is up to you whether you need it.

Yet another typical JavaScript this pitfall.

To be brief, this reference changes in every function scope.
It will only refer to whatever object you’re calling the function on.

You could use the arrow function introduced in the ES6 standard to avoid this problem.
Alternatively, you could explicitly specify the this reference at runtime by calling the .call method of the function’s prototype.