Scene Change On Collision: Help

Hi,

In my game, the scene is supposed to change scenes upon a collision and upon clicking a button. However, it throws up a bunch of errors related to a different script in the game. Please help, this game is quite urgent, I need to submit it by the end of the month.

Editor - https://playcanvas.com/editor/scene/649545

My code for first scene -


var Collider = pc.createScript('collider');

Collider.attributes.add("sceneId", {type: "string", default: "649544", title: "Scene ID to Load"});

//console.log(this.app.root.children);


// initialize code called once per entity
Collider.prototype.initialize = function () {
    
    
    this.entity.collision.on('collisionstart', this.onCollisionStart, this);
    
//name of 1st object
    this.Entity1 = this.app.root.findByName('NewEntity');

//name of 2nd object
    this.Entity2 = this.app.root.findByName('Barrier');
    
//checker
    this.checker = false;
    
};


Collider.prototype.onCollisionStart = function (result) {
    
    //Check to see if Entity1 has hit this object
    if (result.other == this.Entity1 && this.checker === false) {
        this.checker = false;
        this.changeScenes();
        this.entity.script.off('animationBlending.js');
    }

};

Collider.prototype.changeScenes = function() {
    // Get a reference to the current root object
    var oldHierarchy = this.app.root.findByName ('Level1');
    
    // Load the new scene. The scene ID is found by loading the scene in the editor and 
    // taking the number from the URL
    // e.g. If the URL when Scene 1 is loaded is: https://playcanvas.com/editor/scene/649545
    // The ID is the number on the end (649545)
    this.loadScene (this.sceneId, function () {
        // Once the new scene has been loaded, destroy the old one
        oldHierarchy.destroy ();
    });
};

Collider.prototype.loadScene = function (id, callback) {
    // Get the path to the scene
    var url = id  + ".json";
    
    // Load the scenes entity hierarchy
    this.app.loadSceneHierarchy(url, function (err, parent) {
        if (!err) {
            callback(parent);
        } else {
            console.error (err);
        }
    });
};

My code for second scene -


this.app.root.findByName('btn1_one').element.on('click', function (event) {
            alert('success2');
            this.app.root.findByName('Number5').enabled = true;
            this.app.root.findByName('Number5').element.text = answer2.toString();
            this.changeScenes();
        }, this);
        
        
        /*this.app.root.findByName('btn1_one').element.on('touchstart ', function (event) {
            alert('success2');
            this.app.root.findByName('Number5').enabled = true;
            this.app.root.findByName('Number5').element.text = answer2.toString();
        }, this);*/
    }
    
};

// update code called every frame
NumberManagementScr.prototype.update = function(dt) {
    
};


NumberManagementScr.prototype.changeScenes = function() {
    // Get a reference to the current root object
    var oldHierarchy = this.app.root.findByName ('SeqRoot');
    
    // Load the new scene. The scene ID is found by loading the scene in the editor and 
    // taking the number from the URL
    // e.g. If the URL when Scene 1 is loaded is: https://playcanvas.com/editor/scene/649545
    // The ID is the number on the end (649545)
    this.loadScene (this.sceneId, function () {
        // Once the new scene has been loaded, destroy the old one
        oldHierarchy.destroy ();
    });
};

NumberManagementScr.prototype.loadScene = function (id, callback) {
    // Get the path to the scene
    var url = id  + ".json";
    
    // Load the scenes entity hierarchy
    this.app.loadSceneHierarchy(url, function (err, parent) {
        if (!err) {
            callback(parent);
        } else {
            console.error (err);
        }
    });
};

Code upon which errors are based -


var AnimationBlending = pc.createScript('animationBlending');

AnimationBlending.states = {
    idle: {
        animation: 'Playbot_idle'
    },
    punch: {
        animation: 'Playbot_run'
    }
};

// initialize code called once per entity
AnimationBlending.prototype.initialize = function() {
    this.blendTime = 0.2;

    this.setState('idle');

    this.app.keyboard.on(pc.EVENT_KEYDOWN, this.keyDown, this);
    this.app.keyboard.on(pc.EVENT_KEYUP, this.keyUp, this);
};

AnimationBlending.prototype.setState = function (state) {
    var states = AnimationBlending.states;

    this.state = state;
    // Set the current animation, taking 0.2 seconds to blend from
    // the current animation state to the start of the target animation.
    this.entity.animation.play(states[state].animation, this.blendTime);
};

AnimationBlending.prototype.keyDown = function (e) {
    if ((e.key === pc.KEY_W) && (this.state !== 'punch')) {
        this.setState('punch');
    }
};

AnimationBlending.prototype.keyUp = function (e) {
    if ((e.key === pc.KEY_W) && (this.state === 'punch')) {
        this.setState('idle');
    }
};

https://playcanvas.com/editor/scene/655441

The issue was that you had subscribed to events in the animation script but didn’t unsubscribe when it was destroyed.

This meant that there was a listener for the key up event so when you let go in the 2nd scene, it was trying to call a callback on a non existent/destroyed script.

More specifically, this code:

// initialize code called once per entity
AnimationBlending.prototype.initialize = function() {
    this.blendTime = 0.2;

    this.setState('idle');

    this.app.keyboard.on(pc.EVENT_KEYDOWN, this.keyDown, this);
    this.app.keyboard.on(pc.EVENT_KEYUP, this.keyUp, this);
    
    this.on('destroy', this.onDestroy, this);
};


AnimationBlending.prototype.onDestroy = function () {
    this.app.keyboard.off(pc.EVENT_KEYDOWN, this.keyDown, this);
    this.app.keyboard.off(pc.EVENT_KEYUP, this.keyUp, this);
};
1 Like

It works perfectly while moving from the first scene to the second one. However, while moving from the second back to the first, the alert shows twice and then it says error loading scripts - null is not an object (evaluating ‘this.data[name]’). This does not happen in your project, but happens after I edited mine. I even tried forking your project but the problem still exists. Is it related to parsing?

Screenshot -