React hooks for Unity-like updates in react-three-fiber
react-three-update
React hooks for Unity-like updates in react-three-fiber.
npm install react-three-update # or yarn add react-three-update
Unity provides a strict ordering of events that many game developers are familiar with. Meanwhile, react-three-fiber only has useFrame
and lacks a fixed update method. react-three-update solves this by extending useFrame
to have a strict sequence of update hooks along with a fixed frame loop. The updates are executed in the following order: useEarlyUpdate
, useFixedUpdate
, useUpdate
, useLateUpdate
and then rendering.
? Note: By default useFrame
will execute after useLateUpdate
and before rendering. This means most react-three-fiber and Drei components will occur after useLateUpdate
.
How it works
Wrap your game in the Update component and then subscribe your business logic to update events with the hooks.
import { Canvas } from '@react-three/fiber';
import { Update, useEarlyUpdate, useFixedUpdate, useUpdate, useLateUpdate } from 'react-three-update';
function App() {
return (
<Canvas>
<Update>
<Game />
</Update>
</Canvas>
);
}
function Game() {
useEarlyUpdate((state, delta, fixedState) => {
// Do early updates here like input polling.
});
useFixedUpdate((state, stepSize, fixedState) => {
// Updates on a fixed step happen here. This is often physics
// and mutations that need to be deterministic.
// physics.step(stepSize);
});
useUpdate((state, delta, fixedState) => {
// The bulk of your business logic will go here.
});
useLateUpdate((state, delta, fixedState) => {
// Any updates you want to occur right before rendering.
// For example having a camera follow a character who might
// be moved by input, physics or other interactions.
});
return {
/* children */
};
}
More about useFixedUpdate
There is a single fixed update loop that any callback passed into useFixedUpdate
subscribes to, like useFrame
in react-three-fiber. You can set the stepSize
and maxSubsteps
on Update
.
<Update stepSize={1 / 60} maxSubsteps={8}></Update>
Prop | Description | Type | Default |
---|---|---|---|
stepSize |
The rate of the fixed update. 1/60 is 60 frames per second. | number |
1/50 |
maxSubsteps |
The maximum amount of substeps before the loop bails. Only relevant when the framerate drops below the step size. | number |
10 |
? Note: These properties can be updated dynamically during runtime.
Accessing the fixedState
A fixedState
can be accessed from any update hook.
useUpdate((state, delta, fixedState) => { const factor = fixedState.factor }
And has the following properties:
Prop | Description | Type |
---|---|---|
stepSize |
The rate of the fixed update. 1/60 is 60 frames per second. | number |
maxSubsteps |
The maximum amount of substeps before the loop bails. Only relevant when the framerate drops below the step size. | number |
remainder |
The time remaining after a fixed loop is complete. See Fix Your Step. | number |
factor |
The interpolation factor. Calculated by remainder / stepSize . See Fix Your Step. |
number |
This can be useful for manually implementing interpolation for physics or other effects that rely on a fixed update.
Imperative updates with useFixedUpdateApi
You can update the fixed update state imperatively with useFixedUpdateApi
. Like useThree
, the hook is reactive and accepts selectors.
import { useFixedUpdateApi } from 'react-three-update'
// For full state.
function Foo() {
const state = useFixedUpdateApi()
// Or with selector.
function Foo() {
const setStepSize = useFixedUpdateApi((state) => state.setStepSize);