Reputation: 31
I'm using Box3
to detect intersections so player could collect coins. I'd like the coin to be removed after detecting that it's intersecting with player but for some reason, I can't remove its (coin's) Box3
.
I've read the documentation and deduced that Box3
is connected to the item's geometry, but removing the geometry and removing the item from the scene doesn't seem to remove Box3; it just stays in place, still interacting with player.
My code fiddle: https://jsfiddle.net/ImLost/g3mu1fqe/2/
Code:
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();
Upvotes: 1
Views: 793
Reputation: 8886
coinGeometry.dispose()
coin.geometry.dispose()
scene.remove(coin)
The code above does not invalidate your coin
object, nor its .geometry
property--it simply discards the buffer and attribute data from memory. Other properties, like boundingBox
still exist. Otherwise, you would be getting errors when you copy the bounding box into coinBox
after the coin has been "consumed."
Now, you can invalidate the whole coin by setting it to null
:
scene.remove(coin)
coin = null
However, JavaScript is garbage-collected, and you may still be able to access the object before it is actually removed from the heap. I would recommend a simple logical workaround:
scene.remove(coin)
coin.userData.consumed = true
coin = null
Then in your renderer and key event listener, add checks for the new property:
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);
}
Upvotes: 2