Search code examples
webglthree.js

how to let the player control collide with walls in three.js


I have a three.js scene with a big mesh as my map (exported from blender).

I load it so:

// map
var loader = new THREE.JSONLoader(true);
var thiz = this;
loader.load(
    "iceworld.js"
    , function(geometry, materials) {
        materials[0].side = THREE.DoubleSide;
        var faceMaterial = new THREE.MeshLambertMaterial( materials[0] );
        //var faceMaterial = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'ice.jpg' ), side: THREE.DoubleSide } );

       mesh = new THREE.Mesh( geometry, faceMaterial );
       thiz.scene.add( mesh );
     }
);

I use the PointerLockControls. Now I can walk through the map's walls because there is no collision detection.

How can I implement this? I did not find a solution in the examples and documentation.


Solution

  • Three.js is a graphics rendering library and does not concern collision detection. You need something different for that. Here's a few options:

    • If your scene is mostly planar and rectangular, i.e. even though it's 3d, the player only walks on one 2d plane with walls having simple shapes, you could create a simple grid which marks the locations of obstacles and then you check your player's coordinates against the grid and cancel the movement if it ends up inside walls.
    • Use a physics engine: Physijs is an easy-to-use and flexible Bullet dynamics engine wrapper for Three.js. You could wrap your scene mesh inside a single Physijs.ConcaveMesh, add a collision shape to your camera and have instant, accurate collision detection - but that's going to be slow if you have a decently complex scene.
    • A better approach is to break your scene into discrete objects, such as rectangular wall sections and add cheap collision shapes (like cubes, spheres, cylinders) for them individually. Physijs could do that, and then there is cannon.js (see FPS demo here).
    • Roll your own collision detection. I don't really recommend this because it's a rabbit hole, but it will give you full control over what features, accuracy and performance trade-offs are perfect for you.

    Personally, I've created an FPS game with Three.js. My level design is very regular, so I could use the grid method for player collisions, but I also wanted dynamic objects (e.g. barrels, boxes etc.) and using Physijs allowed me to integrate them too almost trivially. The wall collisions are thus handled by creating Physijs cubes to wall sections.