Integrate FirstPersonControls in Three.js
This guide explains how to integrate FirstPersonControls
into a Three.js project to recreate a classic first-person video game
camera. You will learn how to import the controller, initialize it with
your camera and renderer, configure its movement and looking
sensitivity, and update it within the animation loop using a clock.
1. Import the Required Modules
To use FirstPersonControls, you must import it in
addition to the core Three.js library. Modern versions of Three.js
locate these add-ons in the addons directory.
import * as THREE from 'three';
import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js';2. Set Up the Clock and Renderer
FirstPersonControls requires a time delta (the time
elapsed between frames) to calculate smooth, frame-rate-independent
movement. You need to instantiate a THREE.Clock to track
this time.
// Initialize the clock
const clock = new THREE.Clock();
// Standard setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);3. Initialize FirstPersonControls
Instantiate the controls by passing the camera and the renderer’s DOM element.
const controls = new FirstPersonControls(camera, renderer.domElement);4. Configure Control Settings
Customize the movement speed, look speed, and behavior to match your desired video game style.
// Adjust how fast the camera moves (units per second)
controls.movementSpeed = 50;
// Adjust how fast the camera rotates with the mouse
controls.lookSpeed = 0.1;
// Prevent the camera from looking upside down
controls.lookVertical = true;
// Constrain vertical looking angles (optional)
controls.verticalMin = 1.0;
controls.verticalMax = 2.0;
// Allow camera rotation only when clicking and dragging (false),
// or constantly tracking the mouse position (true)
controls.activeLook = true;5. Update Controls in the Animation Loop
To make the camera move and look around, you must update the controls
on every frame. Pass the elapsed time delta from your clock into the
controls.update() method.
function animate() {
requestAnimationFrame(animate);
// Get the time elapsed since the last frame
const delta = clock.getDelta();
// Update the controls
controls.update(delta);
// Render the scene
renderer.render(scene, camera);
}
animate();6. Handle Window Resizing
If the browser window is resized, the controls need to be notified to recalculate their internal dimensions.
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
// Update controls to match new dimensions
controls.handleResize();
});