Why does the code stop in react-three-fiber?

  Kiến thức lập trình

I am making a game through react-three-fiber for the first time.

I created the above code to create a character controller and move the box with the keyboard.

However, after refreshing, the box moves for a few seconds, then stops, and does not move even when I use the keyboard.

Why is that?

And when I jump, the box comes down too slowly.

What went wrong?

The box comes down so slowly,,,,,

I don’t know how to solve both problems.

// components/Player.tsx
import { Box } from "@react-three/drei";
import {RapierRigidBody, RigidBody} from "@react-three/rapier";
import {usePersonController} from "./controller.tsx";
import {useRef} from "react";
import {useFrame} from "@react-three/fiber";
import {Vector3} from "three";

export const Player = () => {
    const movementState = usePersonController()
    const rigidBodyRef = useRef<RapierRigidBody>(null)

    useFrame(() => {
        if (rigidBodyRef.current) {
            const vector = new Vector3(
                movementState.left ? -1 : movementState.right ? 1 : 0,
                movementState.jump ? 1 : 0,
                movementState.forward ? -1 : movementState.backward ? 1 : 0
            ).multiplyScalar(5)
            rigidBodyRef.current.setLinvel(vector, false)
        }
    })

    return (
        <RigidBody ref={rigidBodyRef} position={[0,  0, 0]} mass={100}>
            <Box />
        </RigidBody>
    );
};

After the first refresh, it moves for a few seconds and then suddenly stops. addEventListener continues to work, but the Box does not move.

When you jump, the box goes down very slowly. It goes down so slowly that it seems like the gravity part is applied strangely.

This is the full code I wrote

App.tsx

// App.tsx
import './App.css';
import { Canvas } from '@react-three/fiber';
import { Physics } from '@react-three/rapier';
import { OrbitControls } from '@react-three/drei';
import Plane from "./components/plane.tsx";
import {Player} from "./components/player.tsx";

function App() {
    return (
        <Canvas shadows camera={{ position: [0, 5, 10], fov: 45 }}>
            <ambientLight intensity={0.5} />
            <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} castShadow />
            <directionalLight position={[-10, 10, -10]} intensity={0.5} castShadow />
            <OrbitControls />
            <Physics>
                <Plane />
                <Player />
            </Physics>
        </Canvas>
    );
}

export default App;

controller.tsx

import {useEffect, useState} from "react";

type Movement = {
    forward: boolean;
    backward: boolean;
    left: boolean;
    right: boolean;
    jump: boolean;
}

export const usePersonController = (): Movement => {
    const [movement, setMovement] = useState<Movement>({
        backward: false,
        forward: false,
        jump: false,
        left: false,
        right: false
    });

    useEffect(() => {
        const keys : {[key: string]: keyof Movement} = {
            KeyW: 'forward',
            KeyS: 'backward',
            KeyA: 'left',
            KeyD: 'right',
            Space: 'jump',
        }
        const moveFieldByKey = (key: string): keyof Movement => keys[key];

        const keyDown = (e: KeyboardEvent) => {
            console.log(1)
            setMovement(prev => ({...prev, [moveFieldByKey(e.code)]: true}));
        }

        const keyUp = (e: KeyboardEvent) => {
            console.log(2)
            setMovement(prev => ({...prev, [moveFieldByKey(e.code)]: false}));
        }

        window.addEventListener('keydown', keyDown)
        window.addEventListener('keyup', keyUp)

        return () => {
            window.addEventListener('keydown', keyDown)
            window.addEventListener('keyup', keyUp)
        }
    }, []);


    return movement

}
// Plane.js
import {RigidBody} from '@react-three/rapier';

export default function Plane() {
    return (
        <RigidBody type={'fixed'}>
            <mesh rotation={[-Math.PI / 2, 0 ,0]} receiveShadow={true}>
                <planeGeometry args={[100, 100]} />
                <meshStandardMaterial color={'lightblue'} />
            </mesh>
        </RigidBody>
    );
}
// components/Player.tsx
import { Box } from "@react-three/drei";
import {RapierRigidBody, RigidBody} from "@react-three/rapier";
import {usePersonController} from "./controller.tsx";
import {useRef} from "react";
import {useFrame} from "@react-three/fiber";
import {Vector3} from "three";

export const Player = () => {
    const movementState = usePersonController()
    const rigidBodyRef = useRef<RapierRigidBody>(null)

    useFrame(() => {
        if (rigidBodyRef.current) {
            const vector = new Vector3(
                movementState.left ? -1 : movementState.right ? 1 : 0,
                movementState.jump ? 1 : 0,
                movementState.forward ? -1 : movementState.backward ? 1 : 0
            ).multiplyScalar(5)
            rigidBodyRef.current.setLinvel(vector, false)
        }
    })

    return (
        <RigidBody ref={rigidBodyRef} position={[0,  0, 0]} mass={100}>
            <Box />
        </RigidBody>
    );
};

I’m just starting out and I’m missing a lot of things. I would appreciate it if you could give me some hints.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT