pmndrs / react-three-rapier

🤺 Rapier physics in React
https://react-three-rapier.pmnd.rs
MIT License
1.1k stars 62 forks source link

Update of World Position best practices #618

Closed rmrbytes closed 7 months ago

rmrbytes commented 9 months ago

Hello:

When a body is falling the world position of that body get continously updated. I have access to this using the useFrame hook. I need to display this updated value to be stored and available elsewhere. For the same I am using setState though it is not recommended to be used with useFrame. Is there a better way to get this value? My current code is:

...
// called from App.js
const Ring = (({ color, restitution, position, size, updatePos, ...props }) => {

    const ref = useRef();
    let vec = new THREE.Vector3(0, 0, 0);

    useFrame(() => {
      ref.current.getWorldPosition(vec);
     // the below is the referenced method from parent that is used in this component
      updatePos(vec); 
    }, [ref.current]);

    return (
      <RigidBody colliders={"trimesh"} restitution={restitution} rotation={[-Math.PI / 2, 0, 0]} position={position} >
        <mesh ref={ref}>
          <torusGeometry args={size} />
          <meshBasicMaterial color={color} />
        </mesh>
      </RigidBody>
    )
  });

Thanks.

DennisSmolek commented 7 months ago

The two ways I would do it are

  1. Create a throttle function in that fires from the useFrame. Set it to a reasonable limit. This function would throttle the number of react calls to whatever you want.
  2. and what I'd probably do myself, is simply create your own loop on a different interval. Use something like this useSetInterval hook and make your own loop to call the ref.current.getWorldPosition(vec);

The reason for all this is updating react is annoying and slow. If it remounts a component it can cause multiple useless cycles and creations of things, and the traversing of the tree takes forever. Doing this at frame rate speeds is super CPU intense and will likely bog things down. So either use a throttle and the default useFrame loop, or create your own loop.

rmrbytes commented 7 months ago

Thanks @DennisSmolek . I will probably follow option 2 that we would normally use in vanilla JS