Cameras, Mesh Collisions and Gravity
Did you ever play a FPS (First Person Shooter) game? In this tutorial, we are going to simulate the same camera movements: the camera is on the floor, in collision with the ground, and potentially in collision with any objects in the scene.
How can I do this ?
To replicate this movement, we have to do 3 simple steps:
1 - Define and apply gravity
The first thing to do is to define our gravity vector, defining the G-force. In a classic world such as Earth, the direction of the force of gravity is down (negative) along the Y axis, but feel free to change it!
scene.gravity = new BABYLON.Vector3(0, -9.81, 0);
Gravity can be applied to any camera that you have defined previously in your code.
camera.applyGravity = true;
2 - Define an ellipsoid
The next important step is to define the ellipsoid around our camera. This ellipsoid represents our player’s dimensions: a collision event will be raised when a mesh comes in contact with this ellipsoid, preventing our camera from getting too close to this mesh:
The ellipsoid property on babylon.js cameras is default to size (0.5, 1, 0.5), but changing values will make you taller, bigger, smaller, thinner, it depends upon the adjusted axis. In the example below, we will make our camera's ellipsoid a bit bigger than the default one:
//Set the ellipsoid around the camera (e.g. your player's size)camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);
Please note that the ellipsoid for the camera is offset to always have the view point on top of the ellipsoid. You can control this behavior by updating the
The computation will be the following:
finalPosition = position - vec3(0, ellipsoid.y, 0) + ellipsoidOffset
3 - Apply collision
Once you have those previous settings completed, our final step is to declare that we are interested in sensing collisions in our scene:
// Enable Collisionsscene.collisionsEnabled = true;camera.checkCollisions = true;
And declare which meshes could be in collision with our camera:
ground.checkCollisions = true;box.checkCollisions = true;
That’s it! Easy!
Now, your camera is going to fall on the y-axis until it collides with the ground. And, your camera will collide with the box when you move it too near to it.
4 - Object vs. object collision
You can also do the same thing with a mesh by playing with mesh.ellipsoid property and mesh.moveWithCollisions(velocity) function. This function will try to move the mesh according to given velocity and will check if there is no collision between current mesh and all meshes with checkCollisions activated.
You can also use mesh.ellipsoidOffset to move the ellipsoid on the mesh (By default the ellipsoid is centered on the mesh)
var speedCharacter = 8;var gravity = 0.15;var character = Your mesh;character.ellipsoid = new BABYLON.Vector3(0.5, 1.0, 0.5);character.ellipsoidOffset = new BABYLON.Vector3(0, 1.0, 0);var forwards = new BABYLON.Vector3(parseFloat(Math.sin(character.rotation.y)) / speedCharacter, gravity, parseFloat(Math.cos(character.rotation.y)) / speedCharacter);forwards.negate();character.moveWithCollisions(forwards);// orvar backwards = new BABYLON.Vector3(parseFloat(Math.sin(character.rotation.y)) / speedCharacter, -gravity, parseFloat(Math.cos(character.rotation.y)) / speedCharacter);character.moveWithCollisions(backwards);
The ArcRotateCamera can also check collisions but instead of sliding along obstacles, this camera won't move when a collision appends.
To activate collisions, just call
camera.checkCollisions = true. You can define the collision radius with this code:
camera.collisionRadius = new BABYLON.Vector3(0.5, 0.5, 0.5)
Other Types of Collisions
Great, now you can develop a real FPS game! But maybe you would like to know when a mesh is in collision with another mesh? If that interests you, you can head on over here: Mesh Collisions.