Error from time to time

I have a script that make monsters NPC appear in my project, and sometime I get an error and sometimes not, which is quite puzzling, can someone help me to try to figure this out?

Error is : TypeError: Cannot read properties of undefined (reading 'reset')
    at https://launch.playcanvas.com/api/assets/files/Relavia/MinusVille/MinusVille%20script/MonsterAppear.js?id=239601191&branchId=f108d0b9-516f-4e47-a413-bd2c84833c14:82:34.   var MonsterAppear = pc.createScript('monsterAppear');

script is :

var MonsterAppear = pc.createScript('monsterAppear');

// Monstres à faire apparaître
MonsterAppear.attributes.add('monster4',  { type: 'entity', title: 'Monstre -4 (4appear)' });
MonsterAppear.attributes.add('monster5',  { type: 'entity', title: 'Monstre -5 (5appear)' });
MonsterAppear.attributes.add('monster9',  { type: 'entity', title: 'Monstre -9 (9appear)' });
MonsterAppear.attributes.add('monsterP1', { type: 'entity', title: 'Monstre +1 (+1appear)' });
MonsterAppear.attributes.add('monsterP5', { type: 'entity', title: 'Monstre +5 (+5appear)' });

// Position repère pour particules
MonsterAppear.attributes.add('number4',  { type: 'entity', title: 'Box du Monstre -4' });
MonsterAppear.attributes.add('number5',  { type: 'entity', title: 'Box du Monstre -5' });
MonsterAppear.attributes.add('number9',  { type: 'entity', title: 'Box du Monstre -9' });
MonsterAppear.attributes.add('numberP1', { type: 'entity', title: 'Box du Monstre +1' });
MonsterAppear.attributes.add('numberP5', { type: 'entity', title: 'Box du Monstre +5' });

// Effet de particules à cloner
MonsterAppear.attributes.add('spawnEffectTemplate', { type: 'entity', title: 'Effet de spawn à cloner' });

// Paramètres de clignotement
MonsterAppear.attributes.add('blinkDuration', { type: 'number', default: 1.0, title: 'Durée clignotement (s)' });
MonsterAppear.attributes.add('blinkInterval', { type: 'number', default: 0.15, title: 'Intervalle max clignotement (s)' });

MonsterAppear.prototype.initialize = function () {
    this.setupBlink(this.monster4,  this.number4,  '4appear');
    this.setupBlink(this.monster5,  this.number5,  '5appear');
    this.setupBlink(this.monster9,  this.number9,  '9appear');
    this.setupBlink(this.monsterP1, this.numberP1, '+1appear');
    this.setupBlink(this.monsterP5, this.numberP5, '+5appear');
};

MonsterAppear.prototype.setupBlink = function (monster, numberBox, eventName) {
    monster.enabled = false;

    this.app.on(eventName, () => {
        let blinkTimer = 0;
        let totalBlinkTime = 0;
        let blinking = true;

        // Préparer l’effet de particule
        const effect = this.spawnEffectTemplate.clone();
        effect.enabled = true;
        this.app.root.addChild(effect);

        // Position au-dessus du monstre
        const pos = monster.getPosition().clone();
        pos.y += 1.2;
        effect.setPosition(pos);

        const particles = effect.particlesystem;
        if (particles) {
            particles.reset();
            particles.play();
        }

        const maxInterval = this.blinkInterval;
        const minInterval = this.blinkInterval * 0.2;

        monster.enabled = true;

        const blinkScript = (dt) => {
            if (!blinking) return;

            totalBlinkTime += dt;
            blinkTimer += dt;

            let t = pc.math.clamp(totalBlinkTime / this.blinkDuration, 0, 1);
            let easedT = pc.math.smootherstep(0, 1, t);
            let interval = pc.math.lerp(maxInterval, minInterval, 1 - easedT);

            if (blinkTimer >= interval) {
                monster.enabled = !monster.enabled;
                blinkTimer = 0;
            }

            if (totalBlinkTime >= this.blinkDuration) {
                blinking = false;
                monster.enabled = false;

                setTimeout(() => {
                    monster.enabled = true;
                    monster.anim.reset();
                    monster.anim.setBoolean('idle', true);
                    if (particles) particles.stop();
                    setTimeout(() => effect.destroy(), 1000);
                }, 200);

                this.app.off('update', blinkScript);
            }
        };

        this.app.on('update', blinkScript);
    });
};

thanks in advance

1 Like

Thanks! The issue was caused by monster.anim being undefined sometimes. I fixed it by checking if monster.anim exists before calling reset():

if (monster.anim) {
    monster.anim.reset();
    monster.anim.setBoolean('idle', true);
}

Also made sure all monster entities have the Anim component in the editor. Now it’s working fine without errors.

Hello, M Danish, I could figure this type of protection out, but I was wondering, why it occurs only from time to time… in the same situation, sometime the animation goes right sometimes, it freezes at this particular point. Anyway, I have applied your solution, and for the time being, no problem. Thanks

1 Like

Do you destroy monster entities at any point?

Hi @magicdidier,
You’re absolutely right to wonder why it only happens sometimes — that kind of intermittent issue can be really tricky.

Most likely, the animation component isn’t fully initialized yet at the moment the event fires. This can happen due to timing differences — for example, if the entity is just being enabled or cloned, and the Anim component hasn’t finished setting up internally.

One way to avoid this kind of race condition is to add a small delay before triggering the animation, or to wait for an ‘anim:ready’ or similar event if you’re using a system that emits one. But checking for monster.anim like we did is a good first step to avoid hard crashes.

Glad it’s working fine now! Let me know if the issue pops up again — happy to help.