2
votes

I'm new to three.js and I'm trying out a very basic shooter. The user should shoot a colored crate (box). When he does so, the crate disappears and another random crate appears, and so on.

if (intersects.length > 0) {
             intersects[0].object.material.color.setHex(Math.random() * 0xffffff);
                  scene.remove(object);
                  create_cube();
                  animate();
...

On landing, it works very smoothly. No lag at all. But the more boxes I shoot, the more the game begins to lag.

Am I doing something wrong in terms of memory allocation or garbage collection?

Here's a JSfiddle: https://jsfiddle.net/k0s2nmru/

(while my code works fine as a separate page, it doesn't seem to work when placed inside JSfiddle)

Update:

I've added stats that come with three.js. They keep giving me pretty good frames per second (up to 150 and more), even though the game starts to lag. Maybe I didn't implement it the right way?

2
In addition to Vals suggestions you might consider object pooling. html5rocks.com/en/tutorials/speed/static-mem-pools - Brandon.Blanchard

2 Answers

5
votes

At first glance, I see 3 ways to optimize your code

1) Don't call animate or render when it isn't necessary

    function onDocumentMouseDown(event) {
        var mouse3D = new THREE.Vector3();
        var raycaster = new THREE.Raycaster();
        mouse3D.normalize();
        controls.getDirection(mouse3D);
        raycaster.set(controls.getObject().position, mouse3D);
        var intersects = raycaster.intersectObjects(objects);
        if (intersects.length > 0) {
     intersects[0].object.material.color.setHex(Math.random() * 0xffffff);
          scene.remove(object);
          create_cube();
          animate();     //  DON'T DO THIS

        }
        renderer.render(scene, camera);   //  DON'T DO THIS
      }

The render is done in a tight loop, controlled by requestAnimationFrame. Not only you don't need to call them outside of the loop, you are ruining the requestAnimationFrame optimizations if you do it (there are several instances of the loop running concurrently)

2) always try to make the render optimal.

     controls.getObject().translateX(velocity.x * delta);
     controls.getObject().translateY(velocity.y * delta);
     controls.getObject().translateZ(velocity.z * delta);

     if (controls.getObject().position.y < 10) {

Why not create a temporary variable with the result of controls.getObject() ?

3) Reuse whatever you can

In the line of yomotsu answer, but a little bit different : why not turn off the visibility of the cube that has been hit, change its color and position, and make it visible again ?

1
votes

When you remove a object, you have to remove geometry material and texture which used in the object as well. because resources are cached in the renderer.

scene.remove( mesh );
// clean up
geometry.dispose();
material.dispose();
texture.dispose();

Check this example. http://threejs.org/examples/#webgl_test_memory