pmndrs / use-cannon

👋💣 physics based hooks for @react-three/fiber
https://cannon.pmnd.rs
2.76k stars 154 forks source link

Basic setup with useBox is wobbling and moving slowly #177

Open wilcoschoneveld opened 3 years ago

wilcoschoneveld commented 3 years ago

Consider the demo as follows:

https://codesandbox.io/s/r3f-basic-demo-forked-t64x8?file=/src/App.js

I created a ground plane using usePlane and placed a box on top using useBox. The objects are wrapped in a <Physics> component and a <Canvas>, both without props.

Issue: The box is wobbling and slowly moving out of place.

How to make this box stay in place?

stockhuman commented 3 years ago

As in the Discord, I have looked into this multiple times now, and I get the same strange behaviours as if this example was made of magic numbers. Upon changing the values of the box, physics or otherwise, I can no longer reproduce this issue.

Edit: CSB

Theonlyhamstertoh commented 3 years ago

I was having the same problem and found that the velocity for the block never reaches 0. I added the following below and resulted in the image after. This is why the blocks are still wobbling though as to why, I have no idea.

 useEffect(() => {
    api.velocity.subscribe((velocity) => console.log(velocity)); 
  }, []);

image

To solve the issue, I added allowSleep={true} to the <Physics /> and in the block, added :

  const [ref, api] = useBox(() => ({
    sleepSpeedLimit: 1, <-- which makes it sleep when velocity is below this if I remember correctly,
  }));

There is one small issue with this and it's that the position of the block will never be perfectly 0, so it would technically be floating off ground by 0.0000001. That's my current understanding of the problem. Please correct me if I'm wrong.

kalnode commented 1 year ago

In my use case (3d dice rolling), material friction seems to be a factor to minimize motion jitter.

Too high (e.g. friction = 1) and objects get stuck into a jittering state more often (especially if they land awkwardly). Too low (e.g. friction = 0) and objects ice-skate around, which is unacceptable.

Through trials I ended on a friction value where the 3d dice have a tiny bit of ice-skating movement when they land, which looks more natural anyways, and at the same time this seems to also minimize jittering states, perhaps because through introducing additional movement, a jittering object has a chance to "solve" itself if you think of jittering being an issue where an element is constantly undecided between two directions.

Example: myPhysicsWorld.defaultContactMaterial.friction = 0.001

In addition, I also tweak...

And finally, as a last-resort, I have a global timer which, after X seconds after the dice roll, I turn off animation for the entire scene (e.g. cancelAnimationFrame(myAnimationHolder)) if it hasn't already been done so by all the dice fully landing. This would freeze a jittering object in whatever state it was in (e.g. not completely flat on the floor).

One way or another, If I didn't cancel scene animation, and an object somehow enters infinite jitter then it's possible CPU usage will spike (e.g. PC fans spin up like crazy).