Skip to content

0.12.x to 0.13.x Migration guide

Hugo Wiledal edited this page Apr 14, 2023 · 1 revision

Ref changes

RigidBodies now contains a direct path to the rapier instance. The RigidBodyApi proxy has been removed completely, which changes how values are returned. Math helpers are now included to make conversions from Rapier primitives easy.

Previously:

import { RigidBodyApi } from '@react-three/rapier'

...

const ref = useRef<RigidBodyApi>()

useEffect(() => {
  if (ref.current) {
    // get translation
    const position = ref.current.translation() // Three.Vector3

    // get raw instance
    const instance = ref.current.raw(); // Rapier.RigidBody
  
    // set translation
    ref.current.setTranslation({x: 0, y: 10, z: 0})
  }
}, [])

Now:

import { vec3, RapierRigidBody } from '@react-three/rapier'

...

const ref = useRef<RapierRigidBody>()

useEffect(() => {
  if (ref.current) {
    // get translation
    const translation = ref.current.translation() // Rapier.Vector
    const position = vec3(translation) // Three.Vector3

    // get raw instance
    const instance = ref.current; // Rapier.RigidBody

    // set translation
    ref.current.setTranslation({x: 0, y: 10, z: 0}, true)
  }
}, [])

Similarly Colliders now also provides a direct path to their Rapier representations in their ref, which previously returned an array.

Previously:

const colliders = useRef()

useEffect(() => {
  const collider = colliders.current[0]  // Rapier.Collider
}, [])

return <BallCollider ref={colliders} />

Now:

import { RapierCollider } from '@react-three/rapier'

...

const collider = useRef<RapierCollider>()

useEffect(() => {
  const collider = colliders.current  // Rapier.Collider
}, [])

return <BallCollider ref={collider} />

Joint hooks

Joint hooks now return a RefObject containing the instance of their Rapier representation.

Previously:

const joint = usePrismaticJoint(bodyA, bodyB, [[0,0,0],[0,0,0],[0,0,0]]) // JointApi

useEffect(() => {
  // get raw instance
  const rawJoint = joint.raw() // Rapier.PrismaticImpulseJoint

  // Access joint api
  joint.raw().configureMotor(2, 2, 10, 5);
}, [])

Now:

const joint = usePrismaticJoint() // ObjectRef<Rapier.PrismaticImpulseJoint>

useEffect(() => {
  // get raw instance
  const rawJoint = joint.current // Rapier.PrismaticImpulseJoint

  // Access joint api
  joint.current.configureMotor(2, 2, 10, 5);
}, [])

InstancedRigidBodies

InstancedRigidBodies is set up in a different way, providing a more streamlined dev experience and allowing for fine-grain control as well as dynamic instance ranges.

Now you provide individual RigidBodyProps for each instance using the instances prop. Each instance are required to have a key set.
Providing compound colliders to assign shape is now controlled via the colliderNodes prop.

Previously:

const positions = Array.from({length: COUNT}).map(() => [1, 2, 3])
const rotations = Array.from({length: COUNT}).map(() => [3,2,1])
const scales = Array.from({length: COUNT}).map(() => [1,1,1])

<InstancedRigidBodies 
  colliders={false}
  positions={positions} 
  rotations={rotations}
  scales={scales}
>
  <instancedMesh args={[null, null, COUNT]}>
     ...
  </instancedMesh>

  <BallCollider args={[1]} />
  <CuboidCollider args={[1,2,1]} />
</InstancedRigidBodies>

Now:

const instances = Array.from({length: COUNT}).map((_, index) => ({
  key: 'instance_' + index,
  position: [1,2,3],
  rotation: [1,2,3],
  scale: [1,1,1],
  restitution: Math.random(),
}))

<InstancedRigidBodies 
  colliders={false}
  instances={instances}
  colliderNodes={[
   <BallCollider args={[1]} />,
   <CuboidCollider args={[1,2,1]} />
  ]}
>
  <instancedMesh args={[null, null, COUNT]}>
     ...
  </instancedMesh>
</InstancedRigidBodies>

The count of a instancedMesh can be changed at runtime, provided there is an instance for it.