Getting morph instance

I have a character, with shape keys both in fbx and glb. I can see the morph work perfectly in the viewer, I am trying to create a face animator script and I get this error message :
[FaceAnimator.js?id=230581935&branchId=7895b615-5486-43ab-875a-92436227e314:26]: Cannot read properties of undefined (reading ‘morph’)

TypeError: Cannot read properties of undefined (reading ‘morph’)
at FaceAnimator.initialize (https://launch.playcanvas.com/api/assets/files/Relavia/habitant/monstereye.FBX/FaceAnimator.js?id=230581935&branchId=7895b615-5486-43ab-875a-92436227e314:26:42)
is there something wrong in my scritp :
[FaceAnimator.js?id=230581935&branchId=7895b615-5486-43ab-875a-92436227e314:26]: Cannot read properties of undefined (reading ‘morph’)

var FaceAnimator = pc.createScript('faceAnimator');

// Liste des morphs à charger avec leurs poids par défaut
FaceAnimator.prototype.morphs = {
    "FronceSourcil": 0,
    "Misclos": 0,
    "OeilFermé": 0,
    "Parle": 0,
    "BoucheOuverte": 0,
    "Sad": 0,
    "Clère": 0,
    "Moue": 0,
    "TireLangue": 0
};

FaceAnimator.prototype.initialize = function () {
    const render = this.entity.render;

    this.morphInstance = render.morphInstance;

    for (const name in this.morphs) {
        const index = this.morphInstance.morph.getTargetIndex(name);
        if (index === -1) {
            console.warn(`❌ Morph "${name}" introuvable.`);
        } else {
            this.morphs[name] = index;
            this.morphInstance.setWeight(index, 0); // Tout à 0 au départ
        }
    }

    console.log("✅ Morph targets prêts :", this.morphs);
};

// Méthode pour activer un morph par son nom
FaceAnimator.prototype.setExpression = function (name, weight = 1.0) {
    if (this.morphs[name] === undefined) {
        console.warn(`❌ Expression "${name}" non reconnue.`);
        return;
    }

    this.morphInstance.setWeight(this.morphs[name], weight);
    console.log(`🎭 Expression "${name}" définie à ${weight}`);
};

Thks in advance

Hi @magicdidier!

It should be something with line 19 of the code above.

What is render.morphInstance?

Maybe there are more problems, but based on the error I guess this.morphInstance is undefined.

See this topic: [SOLVED] Accessing blend keys / morph targets in script

question is, why is it undefined??? Morph are there in the viewer, my scritp is on the only entity with e render, and still it can ’ t fing the morph instance…

Albertos you are the best I pointed out the faulty line to chat GPT (as I am not a java specialist) and he found right away the solution that he was not able to figure out by itself. Hourra, spend the entire afternoon on thos yesterday. For the eventual readers of this post here is the correct script :

var FaceAnimator = pc.createScript('faceAnimator');

// Mapping nom → index des shape keys
FaceAnimator.prototype.morphMap = {};

// Initialisation
FaceAnimator.prototype.initialize = function () {
    // Vérifie la présence du composant render
    if (!this.entity.render || !this.entity.render.meshInstances || this.entity.render.meshInstances.length === 0) {
        console.error("❌ Aucun meshInstance trouvé sur cette entité :", this.entity.name);
        return;
    }

    // Récupère le premier meshInstance
    this.meshInstance = this.entity.render.meshInstances[0];

    // Vérifie la présence de morphInstance et morph
    if (!this.meshInstance.morphInstance || !this.meshInstance.morphInstance.morph) {
        console.error("❌ Aucun morphInstance ou morph trouvé sur :", this.entity.name);
        return;
    }

    // Récupère les morph targets
    const morph = this.meshInstance.morphInstance.morph;

    // Crée un mapping des noms de morphs vers leurs index
    for (let i = 0; i < morph.targets.length; i++) {
        const name = morph.targets[i].name;
        this.morphMap[name] = i;
        console.log(`🔍 Morph target ${i}: ${name}`);
    }

    // Optionnel : tester une expression de démarrage
    // this.playExpression("Parle", 1, 0.5);
};

// Joue une expression faciale en définissant un poids temporairement
FaceAnimator.prototype.playExpression = function (name, weight = 1, duration = 0.5) {
    const index = this.morphMap[name];
    if (index === undefined) {
        console.warn(`⚠️ Morph target "${name}" non trouvé.`);
        return;
    }

    const morphInstance = this.meshInstance.morphInstance;

    // Applique le poids
    morphInstance.setWeight(index, weight);

    // Réinitialise le poids après un délai (durée en secondes)
    this.app.once(`update`, () => {
        setTimeout(() => {
            morphInstance.setWeight(index, 0);
        }, duration * 1000);
    });
};
1 Like