Three.js在移除和创建对象后变得非常缓慢

3
我对three.js很陌生,正在尝试一个非常基础的射击游戏。用户应该射击一个有颜色的木箱。当用户这样做时,箱子会消失,另一个随机的木箱会出现,并且以此类推。
if (intersects.length > 0) {
             intersects[0].object.material.color.setHex(Math.random() * 0xffffff);
                  scene.remove(object);
                  create_cube();
                  animate();
...

降落时,游戏非常流畅,没有任何延迟。但是,我射击的箱子越多,游戏就越卡顿。在内存分配或垃圾回收方面,我做错了什么吗?这里有一个JSfiddle:https://jsfiddle.net/k0s2nmru/ (虽然我的代码作为单独的页面运行良好,但似乎放在JSfiddle中就无法正常工作)更新:我添加了three.js提供的统计数据。它们给出了相当不错的每秒帧数(高达150或更多),尽管游戏开始变得卡顿。也许我没有正确实现它?

除了Val的建议,您可能还考虑对象池。 https://www.html5rocks.com/en/tutorials/speed/static-mem-pools/ - Brandon.Blanchard
2个回答

6
乍一看,我看到了优化代码的三种方法:
1)在不必要的情况下不要调用animate或render函数。
    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
      }

渲染是在紧密的循环中完成的,由requestAnimationFrame控制。不仅你不需要在循环外调用它们,而且如果这样做会破坏requestAnimationFrame的优化(有几个实例同时运行循环)。2)始终尝试使渲染最优。
     controls.getObject().translateX(velocity.x * delta);
     controls.getObject().translateY(velocity.y * delta);
     controls.getObject().translateZ(velocity.z * delta);

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

为什么不使用controls.getObject()的结果创建一个临时变量?

3)尽可能重复利用

与yomotsu的回答类似,但有所不同:为什么不关闭已被击中的立方体的可见性,改变其颜色和位置,然后再使其可见?


1
非常感谢!我已经实现了您提供的三种优化方法,现在它可以流畅运行(我还学到了一些新知识!)。我认为第一种方法获得了最大的性能提升。另外,您知道为什么统计信息会显示不错的每秒帧数吗?我是否将其放在了代码的正确位置? - binoculars
1
当您同时运行多个渲染时,帧率甚至可以比以往更高(在标准PC上,requestAnimationFrame应该避免达到150fps,因为显卡刷新率通常较低),但这并不意味着这是有用的工作。 - vals

1
当您删除一个对象时,还必须删除对象中使用的几何材料和纹理,因为资源被缓存在渲染器中。
scene.remove( mesh );
// clean up
geometry.dispose();
material.dispose();
texture.dispose();

请查看这个示例。 http://threejs.org/examples/#webgl_test_memory


1
感谢您的回复。在检测到点击后,我尝试将 scene.remove( object ); geometrycube3.dispose(); materialcube3.dispose(); 添加到我的代码中,但似乎并没有解决延迟问题。我做错了什么吗?由于我的盒子没有纹理,只有颜色,所以没有使用 texture.dispose(); - binoculars

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接