3

I have a code as below. Although I update the sphere position with every frame (useFrame), it does not reflect on my scene. Can someone please help me understand why it will not work.

PS : I am new to this and am trying to do some quick proof of concepts.

function Marble() {
  const controls = useControls()
  const [sphereRef, sphereApi] = useSphere(() => ({
    type: "Dynamic",
    mass: 1,
    position: [0, 2, 0]
  }));

  
  //sphereApi.position.set([0,0,0])
  //console.log("SHM sphereAPI position", sphereRef.current.position);
  useFrame(() => {
    const { forward, backward, left, right, brake, reset } = controls.current
    if (forward == true) {
      console.log("sphereRef position", sphereRef.current.position);
      console.log("sphereAPI position", sphereApi.position);
      //console.log("model position", model.current.position)
      // sphereApi.velocity.set(2,2,2);
      sphereApi.position.set(5,0,0)
      // sphereRef.current.position.set(5,0,0);
    }
  })

  return (
    <mesh ref={sphereRef} castShadow>
      <sphereBufferGeometry attach="geometry" args={[1, 32, 32]}></sphereBufferGeometry>
      <meshStandardMaterial color="white" />
    </mesh>
  );
})
stm
  • 33
  • 6

1 Answers1

2

( See it online: Stackblitz )

Doing sphereApi.position.set(5,0,0) on every frame, just sets the sphere position to x=5 on every frame.

So you should create a state first to store the x position, then update it on every frame to +=5, and then set the sphere position to it:

const [sphereX, setSphereX] = useState(0);
useFrame(() => {
  setSphereX((sphereX) => sphereX + 0.05); // set state x position to +0.05 (5 is fast)
  sphereApi.position.set(sphereX, 0, 0); // apply the state to the sphere position
});

Also make sure to use allowSleep={false} since changing position directly isn't a physical movement, so the physical scene may get sleep.

Online: Stackblitz

yaya
  • 7,675
  • 1
  • 39
  • 38
  • This does not work either. – stm May 26 '22 at 12:03
  • @stm you should also use a state to change the position of sphere. updated the answer and added a demo. (Please also consider up-voting/accepting the answer if it helped). Happy codding <3 – yaya May 26 '22 at 13:13
  • Thanks a lot for the suggestion !! In the Physics (from cannon), I was using allowSleep. Making this to allowSleep={false} worked. Any pointers on what allowSleep intends to do ? Also, is it optimal to move the body using Cannon library or are there other optimal ways to do it ? FYI, I need to run some basic animations for my website. – stm May 26 '22 at 15:27
  • @stm No problem. About your first question, `allowSleep: physically simulated objects will stop being simulated if they have little to no motion for a set period of time`. my guess is when we manually change position with changing x, it's not really physical movement. (it's like teleportation), so it doesn't get detects as a movement. i think the correct way is to use velocity to move objects, so it counts as physical movement, so `allowSleep` will probably work. About your second question, i'm not so familiar with `threejs`, so i'm not sure about it. maybe exploring some doc examples helps: – yaya May 26 '22 at 15:42
  • https://github.com/pmndrs/use-cannon/tree/master/packages/react-three-cannon-examples/src/demos – yaya May 26 '22 at 15:42
  • (Also note that since you don't seem to need a complex physical enviroment and you just want some animation, i think you can also ignore `allowSleep`. since coding in the physical way and dealing with velocity and other stuffs may be overwhelming for your need and maybe it's more easy to manually move stuffs.). (also if you need allowSleep for performance purposes (when there is no movement), another option is to create a state called `allowSleep`, and based on your movements, set it to true. so the simulation only stopped when you don't have any movements.) – yaya May 26 '22 at 16:07
  • Actually you should never call `setState` from useFrame – David Mar 08 '23 at 18:03