[SOLVED] Destroying components that were programmatically added

I have code that programmatically creates a collision sphere on an enemy Entity and adds listeners to triggerenter and triggerleave using an anonymous function.

//    enemyEntity
var detectionSphere = new pc.Entity();
var selfEntity = this.entity;
detectionSphere.addComponent("collision", {
    type: "sphere",
    radius: this.enemyDetectionRadius
 });
detectionSphere.collision.on("triggerenter", function( other ) {
    if ( other.tags.has("player") ) {
        selfEntity.fire("onplayerdetected");
    }
}, this);
detectionSphere.collision.on("triggerleave", function( other ) {
    if ( other.tags.has("player") ) {
        selfEntity.fire("onplayerundetected");
    }
}, this);
detectionSphere.on("destroy", function() {
        detectionSphere.collision.off("triggerenter");
        detectionSphere.collision.off("triggerleave");
    });
selfEntity.addChild(detectionSphere);

//    bullet
Bullet.prototype.initialize = function() { 
    this.entity.collision.once('collisionstart', this.onCollisionStart, this);
};

Bullet.prototype.onCollisionStart = function(result) {
    if (result.other.tags.has("player")) {
        result.other.fire("onbullethit",this.bulletBaseDamage);
        this.entity.destroy();  
    }
};

When the enemy gets destroy()ed and a bullet hits the collisionComponent just before the enemy is completely destroyed, triggerenter is still fired which leads to an error where the Entity is undefined.

Uncaught TypeError: Cannot read property 'off' of undefined
    at Entity.<anonymous> (enemyController.js?id=29849166&branchId=d7cd3d63-cfa9-4b70-a4cb-3790f97433dc:71)
    at Entity.fire (playcanvas-stable.js:769)
    at Entity.destroy (playcanvas-stable.js:40744)
...

What could be causing this behavior and is there a way to avoid it from happening?

Link to Project

Hi @Jaime_Domingo, nice game!

Most likely the issue here is you shouldn’t be referencing the entity after it gets destroyed. So yes self.entity is undefined after calling destroy().

I think you may not be needing that code at all, since destroying the entity will take care of removing any events you attached to it. Though make sure to test that!

1 Like

Now I’m getting a memory access error when a bullet enters the trigger volume after the enemy Entity has been destroyed.

I’m considering just creating another script to be loaded using script.create() instead of using an anonymous function to do it.

You were right, I didn’t need to manually remove event listeners

I just made a new script specifically just for the detection spheres to fire an event to the enemy Entity when something enters the trigger volumes. No errors as of now.

//    detectionSphere
DetectionSphere.prototype.initialize = function() {    
    var self = this;
    this.entity.collision.on("triggerenter", function ( other ) {
        self.entity.parent.fire("onplayerdetected", other);
    }, this);
    this.entity.collision.on("triggerleave", function( other ) {
        self.entity.parent.fire("onplayerundetected", other);
    }, this);
};
1 Like

Welp, a new issue has arisen. The out-of-bounds error is back but I’ve changed nothing.

Time to go back to the drawing board, I guess. Thanks for the help!

Update: Moved the detectionSphere construction to just before the enemy is instantiated

no more issues!

1 Like