Problem with events

Hi, my english is not very good, but i will try to describe my problem.

There are main character, that kills enemies. Enemies constantly spawn on level by cloning template entity.
My goal is to create slowmotion effect. To achive it I try to use events.

In runtime always happens one of two things:

  1. Slowmo starts, and never ends. (no reaction for event to stop it)
  2. Error: “Cannot read property ‘call’ of undefined”

I’ve made test simple project whith this kind of event, and everything works there.

I think problem in cloning entity of enemy with script ( i don’t know how to solve it), but I could be wrong.
Help me please! I’ve tried a lot of stuff, there is a latest state of code.

Script fragment, that fires event:

Main.prototype.initialize = function() {
    this.slowMo = false;
    this.slowMoTimer = 0;
    
    this.app.ENEMIES_FRONT = [];
    this.app.ENEMIES_BEHIND = [];
};

Main.prototype.update = function(dt) {
    if(this.onStart)
        this.prepareGame();
    
    if(this.app.keyboard.wasPressed(pc.input.KEY_SPACE) && !this.slowMo){
        this.app.fire('main:slow');
        this.slowMo = true;
    }
    if(this.slowMo){
        if(this.slowMoTimer >= this.SlowMoDuration){
            this.stopSlowMo();
        }
        else
            this.slowMoTimer += dt;
    }
};

Main.prototype.stopSlowMo = function(){
    this.slowMo = false;
    this.slowMoTimer = 0;
    this.app.fire('main:normal');
};

For now there are three scripts that react on this event:

  1. script, that creates enemies (cloning entities of enemies, it is looks like there are all fine with reaction on event);
  2. script whith very simple enemy behavior;
  3. script for main character.

First one (fragments):

DirectorVer2.prototype.spawnEnemy = function(type){
    var front = type == 'front';    
    var en = this.Enemy.clone();
    en.enabled = true;    
    this.entity.addChild(en);
    //en.script.enemyAi.initialize();
    var x = this.Hero.getLocalPosition().x;
    if(front)
        x += this.SpawnDelta;
    else
        x -= this.SpawnDelta;
    en.setLocalPosition(x, 0, 0);
    en.script.enemyAi.attackRange = 1.7;
    if(front){
        en.setEulerAngles(0, -90, 0);
        en.script.enemyAi.movementDirection = false;
        en.script.enemyAi.movementSpeed = this.encounterSpeed;
        en.script.enemyAi.setState('walk');
        this.app.ENEMIES_FRONT.push(en);
    }
    else{
        en.setEulerAngles(0, 90, 0);
        en.script.enemyAi.movementDirection = true;
        en.script.enemyAi.movementSpeed = this.followSpeed;
        en.script.enemyAi.setState('run');
        this.app.ENEMIES_BEHIND.push(en);
    }
    en.script.enemyAi.setEventsOn();
    if(this.slowMo)
        en.script.enemyAi.setSlowMotion();
};

DirectorVer2.prototype.initialize = function() {
    this.slowMo = false;
    this.app.on('main:slow', this.setSlowMotion, this);
    this.app.on('main:normal', this.setNormalMotion, this);
};

DirectorVer2.prototype.setSlowMotion = function(){
    this.slowMo = true;
};

DirectorVer2.prototype.setNormalMotion = function(){
    this.slowMo = false;
};

Second (fragments):

EnemyAi.prototype.initialize = function() {
    this.slowMo = false;
    this.app.on('main:slow', this.setSlowMotion, this);
    this.app.on('main:normal', this.setNormalMotion, this);
};

EnemyAi.prototype.setSlowMotion = function(){
    this.movementSpeed /= 4;
    this.entity.animation.speed /= 4; 
    this.slowMo = true;
};

EnemyAi.propertyIsEnumerable.setNormalMotion = function(){
    this.movementSpeed *= 4;
    this.entity.animation.speed *= 4;  
    this.slowMo = false;
};

EnemyAi.prototype.die = function(){
    this.setEventsOff();
    this.isMoving = false;
    this.entity.animation.loop = false;       
    this.dyingProcess = true;
    this.blendTime = 0.01; 
    this.setState('death');
    if(!this.slowMo)
        this.entity.animation.speed = 1.5;
    this.curAnimDuration = this.entity.animation.duration;
};

EnemyAi.prototype.setEventsOff = function(){
    this.entity.script.off('main:normal', this.setNormalMotion, this);
    this.entity.script.off('main:slow', this.setSlowMotion, this);
};

And third (fragments):

MainCharacter.time = {
    normal: {
        animSpeed: 0.9,
        charSpeed: 0.03
    },
    
    slow: {
        animSpeed: 0.9/4,
        charSpeed: 0.03/4
    }
};

MainCharacter.prototype.initialize = function() {
    this.app.on('main:slow', this.setSlowMotion, this);
    this.app.on('main:normal', this.setNormalMotion, this);
};

MainCharacter.prototype.setSlowMotion = function(){
    this.setTime('slow');
    this.slowMo = true;
};

MainCharacter.propertyIsEnumerable.setNormalMotion = function(){
    this.setTime('normal');  
    this.slowMo = false;
};

MainCharacter.prototype.setTime = function(timeSt){
    var timeStates = MainCharacter.time;
    this.timeState = timeSt;
    this.entity.animation.speed = timeStates[timeSt].animSpeed;
    this.speed = timeStates[timeSt].charSpeed;
};

Can you post a link to a project that is showing this issue please along with reproduction steps on how to get the issue to appear?

I don’t know, is that proper way to give link on project. In runtime you should press “space bar” on keyboard. It would fire event.

Note: The debugging tools that come with your browser really help tracking down issues like this. We have a page in our manual on this :slight_smile: http://developer.playcanvas.com/en/user-manual/scripting/debugging/

Also, I wrote the usual steps I take to investigate bugs like this in another thread which may be useful to you: [Solved] Error after make an add to the code

Onto your specific problem, using the debugger, I was able to find the script and the entity that was causing the problem:

This means that one of the scripts on this entity is causing the problem and the error of this type normally means that callback has been setup incorrectly in some way:

Looking at the script, I find the callbacks and noticed a slight issue:

Change it to this and that should fix it :slight_smile: Don’t forget to also fix EnemyAi.js as well.

MainCharacter.prototype.setSlowMotion = function(){
    this.setTime('slow');
    this.slowMo = true;
};

MainCharacter.prototype.setNormalMotion = function(){
    this.setTime('normal');  
    this.slowMo = false;
};

Oh my god, thank you very much. Very stupid from me :grinning:
Now it is working.

I’am using browser debuger, but not so good as you :slight_smile:

I will check your links.
Thank you again :slight_smile: !!!