Home > Blockchain >  Object Becomes Number After Function Call - Javascript
Object Becomes Number After Function Call - Javascript

Time:12-28

I am using Three.js to create an animation, but my animate() function is not working properly. Simplified code below:

let obj;
let camera = new THREE.PerspectiveCamera(fov, asp, near, far);
let scene = new THREE.Scene();
const loader = new THREE.GLTFLoader();
async function init() {
    obj = await loader.loadAsync("./public/modelo/scene.gltf");
    scene.add(obj.scene);
    animate(obj.scene.children[0]);
    renderer.render(scene, camera);
    function animate(objeto){
        console.log(objeto);
        requestAnimationFrame(animate);
        objeto.rotation.z  = 0.005;
        renderer.render(scene, camera);
    }
}
init();

The function works for the first call, but after that I can see things going wrong via my console.log() statement. On the first run of animate(), the line prints out the object, as expected. But, on all ensuing calls, the statement just returns a floating point number that increases greatly with each successive call. I checked and made sure that the object was intact at the end of the first function call, so I'm not sure what's going on here. Any suggestions?

CodePudding user response:

The problem is in this one line in your code:

requestAnimationFrame(animate);

From the MDN documentation for requestAnimationFrame, the callback you pass it - here animate, is:

The function to call when it's time to update your animation for the next repaint. The callback function is passed one single argument, a DOMHighResTimeStamp similar to the one returned by performance.now(), indicating the point in time when requestAnimationFrame() starts to execute callback functions.

In other words, your animate is getting called with a timestamp - which in some ways I imagine behaves much like a number (I'm not personally familiar with what a DOMHighResTimeStamp is), and explains what you're seeing. It certainly won't be getting called with your "objeto" as argument.

To ensure that, just pass in as a callback a function will calls animate with the correct argument. Replace the call above with

requestAnimationFrame(() => { animate(objeto); });

EDIT: or as @Bergi suggests, we can avoid needing an argument at all by simply defining objeto outside animate, in the init function. Since you always call animate with this same argument there's no need to specifically pass it, so your code can just be:

async function init() {
    obj = await loader.loadAsync("./public/modelo/scene.gltf");
    const objeto = obj.scene.children[0];
    scene.add(obj.scene);
    animate();
    renderer.render(scene, camera);
    function animate(){
        console.log(objeto);
        requestAnimationFrame(animate);
        objeto.rotation.z  = 0.005;
        renderer.render(scene, camera);
    }
}
  • Related