0

I am trying to re-create a little game called orbital (just for fun). In this game the player shoots a circle into an arena. This circle stops somewhere in the arena and expands in size until it collides with the arena border or another circle. (See picture below)

Orbital game overview

The issue I have, is that when the circle is expanding, the Rigid-body applied to the circle does not increase in size. It just keeps the size it had when I first created the Rigid-Body.

So the question: How can I cause a re-render of the rigid-body or update its size dynamically? I am using React-Three-Fiber and Rapier JS.

Currently I tried to set the initial size of the circle using the "args" property and then change the size using the "scale" property on the rigid-body. "scale" is using "state" so it does update the shape, just not the rigid body...

Here's my code so you can better understand what I am trying to tell you

import { useRef, useState } from "react";
import { useFrame } from "@react-three/fiber";
import { RigidBody } from "@react-three/rapier";



const Obstacle = ({
    size = [4,4,2,32], 
    position = [0, 0, 0], 
    color = "red",
    id,
    hasCollided = false
}) => {

    const rigidBody = useRef();
    const obstacle = useRef();
    const [scale, setScale] = useState(1);

    useFrame(() => {
        if (obstacle.current.collided == false) {
            setScale(scale + 0.1);
        }
    });
    

    return ( 
        <RigidBody 
            ref={rigidBody}
            colliders="hull"
            friction={0}
            restitution={1.3}
            type="fixed"
            position={position}
            ccd={true}
            onCollisionEnter={() => obstacle.current.collided = true}
            scale={[scale, 1, scale]}
            canSleep={false}
        >
            <mesh 
                ref={obstacle} 
                collided={hasCollided}
            >
                <cylinderGeometry args={size} />
                <meshStandardMaterial color={color} />
            </mesh>
        </RigidBody>
     );
}
 
export default Obstacle;

I tried multiple things like, making sure the rigid-body can't sleep, or changing the type of the rigid-body, changing the args property instead of the scale property, but nothing worked. Oh and if change the initial size of my circle, the rigid-body changes its size just fine, the problem is just when trying to change it during runtime

If anyone can tell me how I can re-render or update a Rigid-Body during runtime I would greatly appreciate it!

1 Answer 1

0
  const [ref, api] = useRigidBody(() => ({ type: 'dynamic', position: [0, 
  2, 0], mass: 1, ...props }));
  const scale = useRef([1, 1, 1]);

  const { contactPairs } = useContactPairs();

  useEffect(() => {
  contactPairs.forEach((pair) => {
  if (pair.bodyA === api || pair.bodyB === api) {
    scale.current = scale.current.map((s) => s * 1.1);
    api.scale.set(...scale.current);
      }
    });
  }, [contactPairs, api]);

Here's a snippet from a previous project instead of using scale directly on rigid body mesh try this to scale the model

      return (
     <mesh ref={ref}>
      .......
     </mesh>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your reply! I have just seen this sorry, will try and tell you if it worked!
I did not manage to make it work how you did it. But for anyone else looking for a solution, apparently it is not possible to scale a rigidBody / collider during runtime. So my solution was to calculate how much I have to scale the object, scale it to the calculated size and then replace it with a new one to re-render the collider/rigidbody

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.