@react-three/rapier 0.7.1 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@ export interface RigidBodyState {
15
15
  scale: Vector3;
16
16
  isSleeping: boolean;
17
17
  }
18
- export declare type RigidBodyStateMap = Map<RigidBody['handle'], RigidBodyState>;
18
+ export declare type RigidBodyStateMap = Map<RigidBody["handle"], RigidBodyState>;
19
19
  export interface ColliderState {
20
20
  collider: Collider;
21
21
  object: Object3D;
@@ -25,7 +25,7 @@ export interface ColliderState {
25
25
  */
26
26
  worldParent: Object3D;
27
27
  }
28
- export declare type ColliderStateMap = Map<Collider['handle'], ColliderState>;
28
+ export declare type ColliderStateMap = Map<Collider["handle"], ColliderState>;
29
29
  export interface RapierContext {
30
30
  rapier: typeof Rapier;
31
31
  world: WorldApi;
@@ -63,11 +63,13 @@ interface RapierWorldProps {
63
63
  /**
64
64
  * Set the timestep for the simulation.
65
65
  * Setting this to a number (eg. 1/60) will run the
66
- * simulation at that framerate.
66
+ * simulation at that framerate. Alternatively, you can set this to
67
+ * "vary", which will cause the simulation to always synchronize with
68
+ * the current frame delta times.
67
69
  *
68
70
  * @defaultValue 1/60
69
71
  */
70
- timeStep?: number;
72
+ timeStep?: number | "vary";
71
73
  /**
72
74
  * Pause the physics simulation
73
75
  *
@@ -1,8 +1,8 @@
1
1
  export * from "./types";
2
2
  export type { RigidBodyApi, WorldApi, InstancedRigidBodyApi } from "./api";
3
- export type { RigidBodyProps } from './RigidBody';
4
- export type { InstancedRigidBodiesProps } from './InstancedRigidBodies';
5
- export type { CylinderColliderProps, BallColliderProps, CapsuleColliderProps, ConeColliderProps, ConvexHullColliderProps, CuboidColliderProps, HeightfieldColliderProps, RoundCuboidColliderProps, TrimeshColliderProps } from './AnyCollider';
3
+ export type { RigidBodyProps } from "./RigidBody";
4
+ export type { InstancedRigidBodiesProps } from "./InstancedRigidBodies";
5
+ export type { CylinderColliderProps, BallColliderProps, CapsuleColliderProps, ConeColliderProps, ConvexHullColliderProps, CuboidColliderProps, HeightfieldColliderProps, RoundCuboidColliderProps, TrimeshColliderProps } from "./AnyCollider";
6
6
  export { Physics } from "./Physics";
7
7
  export { RigidBody } from "./RigidBody";
8
8
  export { MeshCollider } from "./MeshCollider";
@@ -118,19 +118,19 @@ export interface UseColliderOptions<ColliderArgs extends Array<unknown>> {
118
118
  /**
119
119
  * The position of this collider relative to the rigid body
120
120
  */
121
- position?: Vector3Array;
121
+ position?: Object3DProps["position"];
122
122
  /**
123
123
  * The rotation of this collider relative to the rigid body
124
124
  */
125
- rotation?: Vector3Array;
125
+ rotation?: Object3DProps["rotation"];
126
126
  /**
127
127
  * The rotation, as a Quaternion, of this collider relative to the rigid body
128
128
  */
129
- quaternion?: Object3DProps['quaternion'];
129
+ quaternion?: Object3DProps["quaternion"];
130
130
  /**
131
131
  * The scale of this collider relative to the rigid body
132
132
  */
133
- scale?: Object3DProps['scale'];
133
+ scale?: Object3DProps["scale"];
134
134
  /**
135
135
  * Callback when this collider collides with another collider.
136
136
  */
@@ -219,11 +219,11 @@ export interface UseRigidBodyOptions extends ColliderProps {
219
219
  /**
220
220
  * Initial position of the RigidBody
221
221
  */
222
- position?: Vector3Array;
222
+ position?: Object3DProps["position"];
223
223
  /**
224
224
  * Initial rotation of the RigidBody
225
225
  */
226
- rotation?: Vector3Array;
226
+ rotation?: Object3DProps["rotation"];
227
227
  /**
228
228
  * Automatically generate colliders based on meshes inside this
229
229
  * rigid body.
@@ -250,8 +250,8 @@ export interface UseRigidBodyOptions extends ColliderProps {
250
250
  */
251
251
  collisionGroups?: InteractionGroups;
252
252
  /**
253
- * The default solver groups bitmask for all colliders in this rigid body.
254
- * Can be customized per-collider.
253
+ * The default solver groups bitmask for all colliders in this rigid body.
254
+ * Can be customized per-collider.
255
255
  */
256
256
  solverGroups?: InteractionGroups;
257
257
  onSleep?(): void;
@@ -275,7 +275,7 @@ export interface UseRigidBodyOptions extends ColliderProps {
275
275
  /**
276
276
  * Passed down to the object3d representing this collider.
277
277
  */
278
- userData?: Object3DProps['userData'];
278
+ userData?: Object3DProps["userData"];
279
279
  }
280
280
  export declare type SphericalJointParams = [
281
281
  body1Anchor: Vector3Array,
@@ -7,7 +7,6 @@ var React = require('react');
7
7
  var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
- var MathUtils = require('three/src/math/MathUtils');
11
10
  var threeStdlib = require('three-stdlib');
12
11
 
13
12
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -267,27 +266,38 @@ const Physics = ({
267
266
  const [steppingState] = React.useState({
268
267
  accumulator: 0
269
268
  });
269
+ /* Check if the timestep is supposed to be variable. We'll do this here
270
+ once so we don't have to string-check every frame. */
271
+
272
+ const timeStepVariable = _timeStep === "vary";
270
273
  fiber.useFrame((_, dt) => {
271
274
  const world = worldRef.current;
272
275
  if (!world) return;
273
- world.timestep = _timeStep;
274
276
  /**
275
277
  * Fixed timeStep simulation progression
276
278
  * @see https://gafferongames.com/post/fix_your_timestep/
277
- */
278
- // don't step time forwards if paused
279
- // Increase accumulator
279
+ */
280
+
281
+ const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
282
+
283
+ if (timeStepVariable) {
284
+ world.timestep = clampedDelta;
285
+ if (!_paused) world.step(eventQueue);
286
+ } else {
287
+ world.timestep = _timeStep; // don't step time forwards if paused
288
+ // Increase accumulator
280
289
 
281
- steppingState.accumulator += _paused ? 0 : MathUtils.clamp(dt, 0, 0.2);
290
+ steppingState.accumulator += _paused ? 0 : clampedDelta;
282
291
 
283
- if (!_paused) {
284
- while (steppingState.accumulator >= _timeStep) {
285
- world.step(eventQueue);
286
- steppingState.accumulator -= _timeStep;
292
+ if (!_paused) {
293
+ while (steppingState.accumulator >= _timeStep) {
294
+ world.step(eventQueue);
295
+ steppingState.accumulator -= _timeStep;
296
+ }
287
297
  }
288
298
  }
289
299
 
290
- const interpolationAlpha = steppingState.accumulator % _timeStep / _timeStep; // Update meshes
300
+ const interpolationAlpha = timeStepVariable ? 1 : steppingState.accumulator % _timeStep / _timeStep; // Update meshes
291
301
 
292
302
  rigidBodyStates.forEach((state, handle) => {
293
303
  const rigidBody = world.getRigidBody(handle);
@@ -947,7 +957,7 @@ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
947
957
  ignoreMeshColliders
948
958
  }));
949
959
  }
950
- }, [options]);
960
+ }, [options.colliders]);
951
961
  return colliderProps;
952
962
  };
953
963
  const useRigidBody = (options = {}) => {
@@ -1209,12 +1219,13 @@ const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1209
1219
 
1210
1220
  const [object, api, childColliderProps] = useRigidBody(props);
1211
1221
  React.useImperativeHandle(ref, () => api);
1222
+ const contextValue = React.useMemo(() => ({
1223
+ ref: object,
1224
+ api,
1225
+ options: props
1226
+ }), [object, api, props]);
1212
1227
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1213
- value: {
1214
- ref: object,
1215
- api,
1216
- options: props
1217
- }
1228
+ value: contextValue
1218
1229
  }, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
1219
1230
  ref: object
1220
1231
  }, objectProps, {
@@ -1449,6 +1460,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1449
1460
  options = _objectWithoutProperties(props, _excluded);
1450
1461
 
1451
1462
  const instancesRef = React.useRef([]);
1463
+ const rigidBodyRefs = React.useRef([]);
1452
1464
  const instancesRefGetter = React.useRef(() => {
1453
1465
  if (!instancesRef.current) {
1454
1466
  instancesRef.current = [];
@@ -1462,7 +1474,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1462
1474
  const childColliderProps = useChildColliderProps(object, mergedOptions);
1463
1475
  React.useLayoutEffect(() => {
1464
1476
  object.current.updateWorldMatrix(true, false);
1465
- const rigidBodies = instancesRefGetter.current();
1477
+ const instances = instancesRefGetter.current();
1466
1478
  const invertedWorld = object.current.matrixWorld.clone().invert();
1467
1479
  object.current.traverseVisible(mesh => {
1468
1480
  if (mesh instanceof three.InstancedMesh) {
@@ -1474,6 +1486,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1474
1486
 
1475
1487
  const desc = rigidBodyDescFromOptions(props);
1476
1488
  const rigidBody = world.createRigidBody(desc);
1489
+ rigidBodyRefs.current.push(rigidBody);
1477
1490
  const scale = ((_options$scales = options.scales) === null || _options$scales === void 0 ? void 0 : _options$scales[index]) || [1, 1, 1];
1478
1491
  const instanceScale = worldScale.clone().multiply(vectorArrayToVector3(scale));
1479
1492
  rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
@@ -1504,7 +1517,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1504
1517
  }
1505
1518
 
1506
1519
  });
1507
- rigidBodies.push({
1520
+ instances.push({
1508
1521
  rigidBody,
1509
1522
  api
1510
1523
  });
@@ -1512,31 +1525,27 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1512
1525
  }
1513
1526
  });
1514
1527
  return () => {
1515
- rigidBodies.forEach(rb => {
1528
+ instances.forEach(rb => {
1516
1529
  world.removeRigidBody(rb.rigidBody);
1517
1530
  rigidBodyStates.delete(rb.rigidBody.handle);
1518
1531
  });
1532
+ rigidBodyRefs.current = [];
1519
1533
  instancesRef.current = [];
1520
1534
  };
1521
1535
  }, []);
1522
1536
  const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1523
1537
  React.useImperativeHandle(ref, () => api);
1524
- useUpdateRigidBodyOptions({
1525
- current: instancesRef.current.map(({
1526
- rigidBody
1527
- }) => rigidBody)
1528
- }, mergedOptions, rigidBodyStates, false);
1529
- useRigidBodyEvents({
1530
- current: instancesRef.current.map(({
1531
- rigidBody
1532
- }) => rigidBody)
1533
- }, mergedOptions, rigidBodyEvents);
1534
- return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1535
- value: {
1538
+ useUpdateRigidBodyOptions(rigidBodyRefs, mergedOptions, rigidBodyStates, false);
1539
+ useRigidBodyEvents(rigidBodyRefs, mergedOptions, rigidBodyEvents);
1540
+ const contextValue = React.useMemo(() => {
1541
+ return {
1536
1542
  ref: object,
1537
1543
  api,
1538
- options: props
1539
- }
1544
+ options: mergedOptions
1545
+ };
1546
+ }, [api, mergedOptions]);
1547
+ return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1548
+ value: contextValue
1540
1549
  }, /*#__PURE__*/React__default["default"].createElement("object3D", {
1541
1550
  ref: object
1542
1551
  }, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
@@ -7,7 +7,6 @@ var React = require('react');
7
7
  var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
- var MathUtils = require('three/src/math/MathUtils');
11
10
  var threeStdlib = require('three-stdlib');
12
11
 
13
12
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -267,27 +266,38 @@ const Physics = ({
267
266
  const [steppingState] = React.useState({
268
267
  accumulator: 0
269
268
  });
269
+ /* Check if the timestep is supposed to be variable. We'll do this here
270
+ once so we don't have to string-check every frame. */
271
+
272
+ const timeStepVariable = _timeStep === "vary";
270
273
  fiber.useFrame((_, dt) => {
271
274
  const world = worldRef.current;
272
275
  if (!world) return;
273
- world.timestep = _timeStep;
274
276
  /**
275
277
  * Fixed timeStep simulation progression
276
278
  * @see https://gafferongames.com/post/fix_your_timestep/
277
- */
278
- // don't step time forwards if paused
279
- // Increase accumulator
279
+ */
280
+
281
+ const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
282
+
283
+ if (timeStepVariable) {
284
+ world.timestep = clampedDelta;
285
+ if (!_paused) world.step(eventQueue);
286
+ } else {
287
+ world.timestep = _timeStep; // don't step time forwards if paused
288
+ // Increase accumulator
280
289
 
281
- steppingState.accumulator += _paused ? 0 : MathUtils.clamp(dt, 0, 0.2);
290
+ steppingState.accumulator += _paused ? 0 : clampedDelta;
282
291
 
283
- if (!_paused) {
284
- while (steppingState.accumulator >= _timeStep) {
285
- world.step(eventQueue);
286
- steppingState.accumulator -= _timeStep;
292
+ if (!_paused) {
293
+ while (steppingState.accumulator >= _timeStep) {
294
+ world.step(eventQueue);
295
+ steppingState.accumulator -= _timeStep;
296
+ }
287
297
  }
288
298
  }
289
299
 
290
- const interpolationAlpha = steppingState.accumulator % _timeStep / _timeStep; // Update meshes
300
+ const interpolationAlpha = timeStepVariable ? 1 : steppingState.accumulator % _timeStep / _timeStep; // Update meshes
291
301
 
292
302
  rigidBodyStates.forEach((state, handle) => {
293
303
  const rigidBody = world.getRigidBody(handle);
@@ -947,7 +957,7 @@ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
947
957
  ignoreMeshColliders
948
958
  }));
949
959
  }
950
- }, [options]);
960
+ }, [options.colliders]);
951
961
  return colliderProps;
952
962
  };
953
963
  const useRigidBody = (options = {}) => {
@@ -1209,12 +1219,13 @@ const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1209
1219
 
1210
1220
  const [object, api, childColliderProps] = useRigidBody(props);
1211
1221
  React.useImperativeHandle(ref, () => api);
1222
+ const contextValue = React.useMemo(() => ({
1223
+ ref: object,
1224
+ api,
1225
+ options: props
1226
+ }), [object, api, props]);
1212
1227
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1213
- value: {
1214
- ref: object,
1215
- api,
1216
- options: props
1217
- }
1228
+ value: contextValue
1218
1229
  }, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
1219
1230
  ref: object
1220
1231
  }, objectProps, {
@@ -1449,6 +1460,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1449
1460
  options = _objectWithoutProperties(props, _excluded);
1450
1461
 
1451
1462
  const instancesRef = React.useRef([]);
1463
+ const rigidBodyRefs = React.useRef([]);
1452
1464
  const instancesRefGetter = React.useRef(() => {
1453
1465
  if (!instancesRef.current) {
1454
1466
  instancesRef.current = [];
@@ -1462,7 +1474,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1462
1474
  const childColliderProps = useChildColliderProps(object, mergedOptions);
1463
1475
  React.useLayoutEffect(() => {
1464
1476
  object.current.updateWorldMatrix(true, false);
1465
- const rigidBodies = instancesRefGetter.current();
1477
+ const instances = instancesRefGetter.current();
1466
1478
  const invertedWorld = object.current.matrixWorld.clone().invert();
1467
1479
  object.current.traverseVisible(mesh => {
1468
1480
  if (mesh instanceof three.InstancedMesh) {
@@ -1474,6 +1486,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1474
1486
 
1475
1487
  const desc = rigidBodyDescFromOptions(props);
1476
1488
  const rigidBody = world.createRigidBody(desc);
1489
+ rigidBodyRefs.current.push(rigidBody);
1477
1490
  const scale = ((_options$scales = options.scales) === null || _options$scales === void 0 ? void 0 : _options$scales[index]) || [1, 1, 1];
1478
1491
  const instanceScale = worldScale.clone().multiply(vectorArrayToVector3(scale));
1479
1492
  rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
@@ -1504,7 +1517,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1504
1517
  }
1505
1518
 
1506
1519
  });
1507
- rigidBodies.push({
1520
+ instances.push({
1508
1521
  rigidBody,
1509
1522
  api
1510
1523
  });
@@ -1512,31 +1525,27 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1512
1525
  }
1513
1526
  });
1514
1527
  return () => {
1515
- rigidBodies.forEach(rb => {
1528
+ instances.forEach(rb => {
1516
1529
  world.removeRigidBody(rb.rigidBody);
1517
1530
  rigidBodyStates.delete(rb.rigidBody.handle);
1518
1531
  });
1532
+ rigidBodyRefs.current = [];
1519
1533
  instancesRef.current = [];
1520
1534
  };
1521
1535
  }, []);
1522
1536
  const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1523
1537
  React.useImperativeHandle(ref, () => api);
1524
- useUpdateRigidBodyOptions({
1525
- current: instancesRef.current.map(({
1526
- rigidBody
1527
- }) => rigidBody)
1528
- }, mergedOptions, rigidBodyStates, false);
1529
- useRigidBodyEvents({
1530
- current: instancesRef.current.map(({
1531
- rigidBody
1532
- }) => rigidBody)
1533
- }, mergedOptions, rigidBodyEvents);
1534
- return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1535
- value: {
1538
+ useUpdateRigidBodyOptions(rigidBodyRefs, mergedOptions, rigidBodyStates, false);
1539
+ useRigidBodyEvents(rigidBodyRefs, mergedOptions, rigidBodyEvents);
1540
+ const contextValue = React.useMemo(() => {
1541
+ return {
1536
1542
  ref: object,
1537
1543
  api,
1538
- options: props
1539
- }
1544
+ options: mergedOptions
1545
+ };
1546
+ }, [api, mergedOptions]);
1547
+ return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1548
+ value: contextValue
1540
1549
  }, /*#__PURE__*/React__default["default"].createElement("object3D", {
1541
1550
  ref: object
1542
1551
  }, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
@@ -3,8 +3,7 @@ export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as Rapier
3
3
  import React, { useState, useEffect, useRef, useMemo, createContext, useContext, memo, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
4
4
  import { useAsset } from 'use-asset';
5
5
  import { useFrame } from '@react-three/fiber';
6
- import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeBufferGeometry, CapsuleBufferGeometry, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
7
- import { clamp } from 'three/src/math/MathUtils';
6
+ import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeBufferGeometry, CapsuleBufferGeometry, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
8
7
  import { mergeVertices, RoundedBoxGeometry } from 'three-stdlib';
9
8
 
10
9
  const _quaternion = new Quaternion();
@@ -242,27 +241,38 @@ const Physics = ({
242
241
  const [steppingState] = useState({
243
242
  accumulator: 0
244
243
  });
244
+ /* Check if the timestep is supposed to be variable. We'll do this here
245
+ once so we don't have to string-check every frame. */
246
+
247
+ const timeStepVariable = _timeStep === "vary";
245
248
  useFrame((_, dt) => {
246
249
  const world = worldRef.current;
247
250
  if (!world) return;
248
- world.timestep = _timeStep;
249
251
  /**
250
252
  * Fixed timeStep simulation progression
251
253
  * @see https://gafferongames.com/post/fix_your_timestep/
252
- */
253
- // don't step time forwards if paused
254
- // Increase accumulator
254
+ */
255
+
256
+ const clampedDelta = MathUtils.clamp(dt, 0, 0.2);
257
+
258
+ if (timeStepVariable) {
259
+ world.timestep = clampedDelta;
260
+ if (!_paused) world.step(eventQueue);
261
+ } else {
262
+ world.timestep = _timeStep; // don't step time forwards if paused
263
+ // Increase accumulator
255
264
 
256
- steppingState.accumulator += _paused ? 0 : clamp(dt, 0, 0.2);
265
+ steppingState.accumulator += _paused ? 0 : clampedDelta;
257
266
 
258
- if (!_paused) {
259
- while (steppingState.accumulator >= _timeStep) {
260
- world.step(eventQueue);
261
- steppingState.accumulator -= _timeStep;
267
+ if (!_paused) {
268
+ while (steppingState.accumulator >= _timeStep) {
269
+ world.step(eventQueue);
270
+ steppingState.accumulator -= _timeStep;
271
+ }
262
272
  }
263
273
  }
264
274
 
265
- const interpolationAlpha = steppingState.accumulator % _timeStep / _timeStep; // Update meshes
275
+ const interpolationAlpha = timeStepVariable ? 1 : steppingState.accumulator % _timeStep / _timeStep; // Update meshes
266
276
 
267
277
  rigidBodyStates.forEach((state, handle) => {
268
278
  const rigidBody = world.getRigidBody(handle);
@@ -922,7 +932,7 @@ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
922
932
  ignoreMeshColliders
923
933
  }));
924
934
  }
925
- }, [options]);
935
+ }, [options.colliders]);
926
936
  return colliderProps;
927
937
  };
928
938
  const useRigidBody = (options = {}) => {
@@ -1184,12 +1194,13 @@ const RigidBody = /*#__PURE__*/forwardRef((props, ref) => {
1184
1194
 
1185
1195
  const [object, api, childColliderProps] = useRigidBody(props);
1186
1196
  useImperativeHandle(ref, () => api);
1197
+ const contextValue = useMemo(() => ({
1198
+ ref: object,
1199
+ api,
1200
+ options: props
1201
+ }), [object, api, props]);
1187
1202
  return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1188
- value: {
1189
- ref: object,
1190
- api,
1191
- options: props
1192
- }
1203
+ value: contextValue
1193
1204
  }, /*#__PURE__*/React.createElement("object3D", _extends({
1194
1205
  ref: object
1195
1206
  }, objectProps, {
@@ -1424,6 +1435,7 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1424
1435
  options = _objectWithoutProperties(props, _excluded);
1425
1436
 
1426
1437
  const instancesRef = useRef([]);
1438
+ const rigidBodyRefs = useRef([]);
1427
1439
  const instancesRefGetter = useRef(() => {
1428
1440
  if (!instancesRef.current) {
1429
1441
  instancesRef.current = [];
@@ -1437,7 +1449,7 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1437
1449
  const childColliderProps = useChildColliderProps(object, mergedOptions);
1438
1450
  useLayoutEffect(() => {
1439
1451
  object.current.updateWorldMatrix(true, false);
1440
- const rigidBodies = instancesRefGetter.current();
1452
+ const instances = instancesRefGetter.current();
1441
1453
  const invertedWorld = object.current.matrixWorld.clone().invert();
1442
1454
  object.current.traverseVisible(mesh => {
1443
1455
  if (mesh instanceof InstancedMesh) {
@@ -1449,6 +1461,7 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1449
1461
 
1450
1462
  const desc = rigidBodyDescFromOptions(props);
1451
1463
  const rigidBody = world.createRigidBody(desc);
1464
+ rigidBodyRefs.current.push(rigidBody);
1452
1465
  const scale = ((_options$scales = options.scales) === null || _options$scales === void 0 ? void 0 : _options$scales[index]) || [1, 1, 1];
1453
1466
  const instanceScale = worldScale.clone().multiply(vectorArrayToVector3(scale));
1454
1467
  rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
@@ -1479,7 +1492,7 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1479
1492
  }
1480
1493
 
1481
1494
  });
1482
- rigidBodies.push({
1495
+ instances.push({
1483
1496
  rigidBody,
1484
1497
  api
1485
1498
  });
@@ -1487,31 +1500,27 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1487
1500
  }
1488
1501
  });
1489
1502
  return () => {
1490
- rigidBodies.forEach(rb => {
1503
+ instances.forEach(rb => {
1491
1504
  world.removeRigidBody(rb.rigidBody);
1492
1505
  rigidBodyStates.delete(rb.rigidBody.handle);
1493
1506
  });
1507
+ rigidBodyRefs.current = [];
1494
1508
  instancesRef.current = [];
1495
1509
  };
1496
1510
  }, []);
1497
1511
  const api = useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1498
1512
  useImperativeHandle(ref, () => api);
1499
- useUpdateRigidBodyOptions({
1500
- current: instancesRef.current.map(({
1501
- rigidBody
1502
- }) => rigidBody)
1503
- }, mergedOptions, rigidBodyStates, false);
1504
- useRigidBodyEvents({
1505
- current: instancesRef.current.map(({
1506
- rigidBody
1507
- }) => rigidBody)
1508
- }, mergedOptions, rigidBodyEvents);
1509
- return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1510
- value: {
1513
+ useUpdateRigidBodyOptions(rigidBodyRefs, mergedOptions, rigidBodyStates, false);
1514
+ useRigidBodyEvents(rigidBodyRefs, mergedOptions, rigidBodyEvents);
1515
+ const contextValue = useMemo(() => {
1516
+ return {
1511
1517
  ref: object,
1512
1518
  api,
1513
- options: props
1514
- }
1519
+ options: mergedOptions
1520
+ };
1521
+ }, [api, mergedOptions]);
1522
+ return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1523
+ value: contextValue
1515
1524
  }, /*#__PURE__*/React.createElement("object3D", {
1516
1525
  ref: object
1517
1526
  }, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
package/readme.md CHANGED
@@ -141,7 +141,7 @@ const Scene = () => {
141
141
  instancedApi.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
142
142
 
143
143
  // Or update all instances as if they were in an array
144
- instancedApi.forEach(api => {
144
+ instancedApi.forEach((api) => {
145
145
  api.applyImpulse({ x: 0, y: 10, z: 0 });
146
146
  });
147
147
  }, []);
@@ -239,10 +239,10 @@ You may also subscribe to collision events on individual Colliders:
239
239
 
240
240
  ```tsx
241
241
  <CuboidCollider
242
- onCollisionEnter={payload => {
242
+ onCollisionEnter={(payload) => {
243
243
  /* ... */
244
244
  }}
245
- onCollisionExit={payload => {
245
+ onCollisionExit={(payload) => {
246
246
  /* ... */
247
247
  }}
248
248
  />
@@ -309,6 +309,22 @@ A Collider can be set to be a sensor, which means that it will not generate any
309
309
 
310
310
  WIP
311
311
 
312
+ ## Configuring Time Step Size
313
+
314
+ By default, `<Physics>` will simulate the physics world at a fixed rate of 60 frames per second. This can be changed by setting the `timeStep` prop on `<Physics>`:
315
+
316
+ ```tsx
317
+ <Physics timeStep={1 / 30}>{/* ... */}</Physics>
318
+ ```
319
+
320
+ The `timeStep` prop may also be set to `"vary"`, which will cause the simulation's time step to adjust to every frame's frame delta:
321
+
322
+ ```tsx
323
+ <Physics timeStep="vary">{/* ... */}</Physics>
324
+ ```
325
+
326
+ > **Note** This is useful for games that run at variable frame rates, but may cause instability in the simulation. It also prevents the physics simulation from being fully deterministic. Please use with care!
327
+
312
328
  ---
313
329
 
314
330
  ## Roadmap
@@ -326,6 +342,6 @@ In order, but also not necessarily:
326
342
  - [x] InstancedMesh support
327
343
  - [x] Timestep improvements for determinism
328
344
  - [x] Normalize and improve collision events (add events to single Colliders)
329
- - [ ] Add collision events to InstancedRigidBodies
345
+ - [x] Add collision events to InstancedRigidBodies
330
346
  - [ ] Docs
331
347
  - [ ] CodeSandbox examples