First Person Controls

Learn how to configure the SimpleCharacter for first person perspective.

In this tutorial we will configure the SimpleCharacter to use first person controls with the following result:

Here's a preview of this tutorial's result:

import { Sky } from '@react-three/drei'
import { Canvas } from '@react-three/fiber'
import {
Viverse,
SimpleCharacter,
FixedBvhPhysicsBody,
PrototypeBox,
FirstPersonCharacterCameraBehavior,
PointerLockInput,
LocomotionKeyboardInput,
} from '@react-three/viverse'

export default function App() {
return (
 <Canvas
    onClick={(e) => (e.target as HTMLElement).requestPointerLock()}
    style={{ position: 'absolute', inset: '0', touchAction: 'none' }}
  >
    <Viverse>
      <Sky />
      <directionalLight intensity={1.2} position={[-10, 10, -10]} />
      <ambientLight intensity={1} />
      <SimpleCharacter
        model={false}
        input={[LocomotionKeyboardInput, PointerLockInput]}
        cameraBehavior={FirstPersonCharacterCameraBehavior}
      />
      <FixedBvhPhysicsBody>
        <PrototypeBox scale={[10, 1, 15]} position={[0, -0.5, 0]} />
      </FixedBvhPhysicsBody>
    </Viverse>
  </Canvas>
)
}

First, we switch from third-person to first-person camera behavior and hide the character model to prevent the model from occluding the players view.

<SimpleCharacter
  model={false}
  cameraBehavior={FirstPersonCharacterCameraBehavior}
  // ... other props
/>

Changes:

  • model={false} - Hides the character model since in first-person view, you don't want to see your own character
  • cameraBehavior={FirstPersonCharacterCameraBehavior} - Switches from the default third-person camera to first-person camera behavior

Next, you need to set up the appropriate input controls for first-person movement and looking around:

<SimpleCharacter
  input={[LocomotionKeyboardInput, PointerLockInput]}
  // ... other props
/>

Input components:

  • LocomotionKeyboardInput - Handles WASD movement controls for walking around
  • PointerLockInput - Enables mouse look controls for rotating the camera/view direction

Finally, we need to enable pointer locking when the user clicks on the canvas for the PointerLockInput to work properly:

<Canvas
  onClick={(e) => (e.target as HTMLElement).requestPointerLock()}
>
  {/* ... rest of your scene */}
</Canvas>

What this does:

  • onClick={(e) => (e.target as HTMLElement).requestPointerLock()} - When the user clicks anywhere on the canvas, it requests pointer lock, which captures the mouse cursor and allows for unlimited mouse movement for camera control