Cyril
Cyril

Reputation: 1

Scaling a RigidBody during Runtime

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!

Upvotes: 0

Views: 636

Answers (1)

Atomract
Atomract

Reputation: 17

  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>

Upvotes: 0

Related Questions