use-cannon icon indicating copy to clipboard operation
use-cannon copied to clipboard

ref.current.position didn't update

Open jacky0707 opened this issue 2 years ago • 3 comments

👋 Hi there, I was learning react-three-fiber with https://youtu.be/ZnXKmODEFHA?t=961

When I'm try to use camera.position.copy(ref.current.position) to move with the sphere I just created, I found ref.current.position doesn't update.

image image

Here's my code:

export const User = () => {
  // user Sphere
  const { camera } = useThree()
  const [ref, api] = useSphere(() => ({
    mass: 1,
    type: 'Dynamic',
    position: [0, 10, 0],
  }))

  // get movement
  const { moveForward, moveBackward, moveLeft, moveRight } = useKeyboardControls()
  // initial velocity
  const velocity = useRef([0, 0, 0])
  // subscribe to properties to get updates on each frame.
  useEffect(() => {
    const unsubscribe = api.velocity.subscribe((v) =>  velocity.current = v)
    return unsubscribe
  }, [])

  useFrame(() => {
    camera.position.copy(ref.current.position)

    // get direction
    const direction = new Vector3()
    // horizontal direction, z-direction
    const frontVector = new Vector3(0, 0, Number(moveBackward) - Number(moveForward))
    // horizontal direction, x-direction
    const sideVector = new Vector3(Number(moveLeft) - Number(moveRight), 0, 0)

    // vertical, y-direction
    const SPEED = speedUp ? 15 : 5

    // apply horizontal movement to direction
    direction
      .subVectors(frontVector, sideVector)
      .normalize()
      .multiplyScalar(SPEED)
      .applyEuler(camera.rotation)

    api.velocity.set(direction.x, velocity.current[1], direction.z)
  })

  return (
    <>
      <mesh ref={ref}>
        <sphereGeometry />
      </mesh>
    </>
  )
}

and my dependency:

    "@react-three/cannon": "^6.3.0",
    "@react-three/drei": "^9.4.3",
    "@react-three/fiber": "^8.0.11",

jacky0707 avatar Apr 19 '22 14:04 jacky0707

hi, You have to get the position from API by subscribing it like you did with velocity :

 const pos = useRef(new THREE.Vector3(0, 0, 0));
  useEffect(
    () =>
      api.position.subscribe((v) => {
        return (pos.current = new THREE.Vector3(v[0], v[1], v[2]));
      }),
    []
  );

and then try to apply to the camera camera.position.copy(pos)

Russo-creation avatar Apr 27 '22 23:04 Russo-creation

get the position from API by subscribing it like you did with velocity :

 const pos = useRef(new THREE.Vector3(0, 0, 0));

this help me fix this issue, thank you very much.

however I still have some queries point on this issue,

  1. current I'm able to move with the sphere, but ref.current.position still didn't update value when ref is from
const [ref, api] = useSphere(() => ({
    mass: 1,
    type: 'Dynamic',
    position: [0, 10, 0],
  }))

same code as above works when I'm using

"@react-three/cannon": "^2.2.1",
"@react-three/drei": "^6.0.5",
"@react-three/fiber": "^7.0.1",
  1. If in recent version we'll need to subscribe position from api, in what case will we use ref from useSphere?

jacky0707 avatar Apr 30 '22 16:04 jacky0707

I ended up subscribing and setting the position and quaternion components manually:

  const [bodyRef, physicsApi] = useCompoundBody(/* ... */)

  useEffect(() => {
    return physicsApi.position.subscribe((v) => {
      bodyRef.current.position.fromArray(v);
    });
  }, [physicsApi, bodyRef]);

  useEffect(() => {
    return physicsApi.quaternion.subscribe((v) => {
      bodyRef.current.quaternion.fromArray(v);
    });
  }, [physicsApi, bodyRef]);

Then I could do stuff like this successfully:

otherObject.position.copy(bodyRef.current.position);
otherObject.quaternion.copy(bodyRef.current.quaternion);

🤔 Does using existing bodyRef.current.position instead of a new pos vector as proposed above have any disadvantages?

Glavin001 avatar May 18 '22 06:05 Glavin001