如何删除 ThreeJS 中的 Box3?

How to remove Box3 in ThreeJS?

我正在使用 Box3 来检测路口,以便玩家可以收集硬币。我希望在检测到硬币与玩家相交后将其移除,但由于某种原因,我无法移除它的(硬币)Box3.

我已经阅读了文档并推断出 Box3 与项目的几何形状相关联,但是移除几何形状并从场景中移除项目似乎并没有移除 Box3;它只是留在原地,仍然与玩家互动。

我的代码fiddle:https://jsfiddle.net/ImLost/g3mu1fqe/2/

代码:

        function main() {
            const canvas = document.querySelector('#canva');
            const renderer = new THREE.WebGLRenderer({ canvas });
            renderer.setSize(window.innerWidth, window.innerHeight);

            /* Camera */
            const fov = 40;
            const aspect = window.innerWidth / window.innerHeight;
            const near = 0.1;
            const far = 1000;
            const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
           
            camera.position.set(0, 65, -45);
            camera.up.set(0, 0, 1);
            camera.lookAt(0, 0, 0);

            const scene = new THREE.Scene();

            /* Lights */
            const mainLight = new THREE.DirectionalLight(0xffffff, .85);
            mainLight.position.set(0, 20, 0);
            scene.add(mainLight);
            mainLight.castShadow = true;
            mainLight.shadow.mapSize.width = 2048;
            mainLight.shadow.mapSize.height = 2048;

  
            /* Board */
            const boardGeometry = new THREE.PlaneGeometry(50, 50);
            const boardMaterial = new THREE.MeshToonMaterial({ color: 0xEEEEEE, side: THREE.DoubleSide });
            const board = new THREE.Mesh(boardGeometry, boardMaterial);
            board.rotation.x = Math.PI / 2; //The board must be placed flat on the x axis
            scene.add(board);

            /* Player */
            const playerBox = new THREE.Box3() // Used to determine collisions

            const playerGeometry = new THREE.BoxGeometry(1, 1, 1.5);
            const playerMaterial = new THREE.MeshToonMaterial({ color: 0xAAAAAA });
            const player = new THREE.Mesh(playerGeometry, playerMaterial);

            player.geometry.computeBoundingBox(playerBox);
            scene.add(player);

            /* Box helper */
            const playerHelper = new THREE.Box3Helper(playerBox, 0xffff00);
            scene.add(playerHelper);


            /* Coin */
            const smallCollectibleRadius = .4
            const bigCollectibleRadius = .6

            const coinBox = new THREE.Box3();

            const coinGeometry = new THREE.SphereGeometry(smallCollectibleRadius, 100, 100);
            const coinMaterial = new THREE.MeshToonMaterial({ color: 0xffff00, emissive: 0xffff00 });
            const coin = new THREE.Mesh(coinGeometry, coinMaterial);
            coin.position.set(0, 0, 3)
            scene.add(coin);

            coin.geometry.computeBoundingBox(coinBox);

            const coinHelper = new THREE.Box3Helper(coinBox, 0xffff00);
            scene.add(coinHelper);

            function checkCollision(box) {
                var collision = playerBox.intersectsBox(box);
                if (collision == true) {
                    return true
                }
            }

            document.addEventListener("keypress", function (event) {
                if (checkCollision(coinBox)) {
                    console.log("Yummy coin!")
                    coinGeometry.dispose()
                    coin.geometry.dispose()
                    scene.remove(coin)
                }
            });

            function render(time) {
                time *= 0.001;
                const speed = 0.0005
                const rotSpeed = 0.00005
                const dir = new THREE.Vector3();

                playerBox.copy(player.geometry.boundingBox).applyMatrix4(player.matrixWorld);
                coinBox.copy(coin.geometry.boundingBox).applyMatrix4(coin.matrixWorld);

                document.addEventListener("keypress", function (event) {
                    if (event.keyCode == 119) {
                        player.getWorldDirection(dir);
                        player.position.addScaledVector(dir, speed);
                    }
                    if (event.keyCode == 115) {
                        player.getWorldDirection(dir);
                        player.position.addScaledVector(dir, -speed);
                    }

                    if (event.keyCode == 97) {
                        player.rotation.y += rotSpeed
                    }

                    if (event.keyCode == 100) {
                        player.rotation.y -= rotSpeed
                    }
                });

                renderer.render(scene, camera);

                requestAnimationFrame(render);
            }

            requestAnimationFrame(render);
        }

        main();
coinGeometry.dispose()
coin.geometry.dispose()
scene.remove(coin)

上面的代码不会使您的 coin 对象无效,也不会使它的 .geometry 属性 对象无效——它只是从内存中丢弃缓冲区和属性数据。其他属性,如 boundingBox 仍然存在。否则,当您将边界框复制到 coinBox 之后 硬币被“消耗”时,您会遇到错误。

现在,您可以通过将其设置为 null:

来使整个硬币失效
scene.remove(coin)
coin = null

但是,JavaScript 是垃圾回收的,您仍然可以在对象实际从堆中删除之前访问该对象。我会推荐一个简单的逻辑解决方法:

scene.remove(coin)
coin.userData.consumed = true
coin = null

然后在您的渲染器和关键事件侦听器中,添加对新 属性:

的检查
document.addEventListener("keypress", function (event) {
  if (coin !== null && !('consumed' in coin.userData) && checkCollision(coinBox)) {
playerBox.copy(player.geometry.boundingBox).applyMatrix4(player.matrixWorld);
if( coin !== null && !('consumed' in coin.userData) ){
  coinBox.copy(coin.geometry.boundingBox).applyMatrix4(coin.matrixWorld);
}