React 三光纤播放器组件在静止一段时间后停止移动

问题描述 投票:0回答:1

我有一个 React Three Fiber 应用程序,用户可以像 FPS 一样移动玩家。它的效果很好,直到你停止移动超过 3 秒,然后如果你尝试再次移动,玩家将不会移动,我仍然可以移动相机,但键盘控件都不起作用。这是我的代码 Home.jsx(创建画布的位置)

import { KeyboardControls, PointerLockControls, Sky } from '@react-three/drei'
import { Canvas } from '@react-three/fiber'
import { Physics, RigidBody } from '@react-three/rapier'
import React, { useEffect } from 'react'
import { Player } from '../components/3d/Player'
import '../css/Home.css'
import Scene from '../components/3d/Scene'

const Home = () => {

    useEffect(() => {
        // Add event listener for the 'Escape' key press
        const handleKeyDown = (event) => {
            if (event.key === 'Escape') {
                document.exitPointerLock(); // Release pointer lock
            }
        };

        document.addEventListener('keydown', handleKeyDown);

        return () => {
            // Clean up event listener
            document.removeEventListener('keydown', handleKeyDown);
        };
    }, []);

    
    return (
        <section >


            <div>
                <KeyboardControls
                    map={[
                        { name: "forward", keys: ["ArrowUp", "w", "W"] },
                        { name: "backward", keys: ["ArrowDown", "s", "S"] },
                        { name: "left", keys: ["ArrowLeft", "a", "A"] },
                        { name: "right", keys: ["ArrowRight", "d", "D"] },
                        { name: "jump", keys: ["Space"] },
                        { name: 'run', keys: ['Shift'] },
                        { name: 'crouch', keys: ['ControlLeft']}
                    ]}>
                    <Canvas id='canvas'shadows camera={{ fove: 50 }} className='canvas' onKeyDown={(e)=>{console.log(e)}}>
                        <Sky sunPosition={[100, 20, 100]} />
                        <ambientLight intensity={1} />
                        <pointLight castShadow intensity={0.8} position={[100, 100, 100]} />
                        <Physics gravity={[0, -30, 0]}>
                            <Scene scale={1}/>
                            
                            <Player />
                        </Physics>
                        <PointerLockControls />
                    </Canvas>
                </KeyboardControls>
            </div>
        </section>
    )
}

export default Home

Player.jsx

import * as THREE from "three"
import * as RAPIER from "@dimforge/rapier3d-compat"
import { useRef, useState } from "react"
import { useFrame } from "@react-three/fiber"
import { useKeyboardControls } from "@react-three/drei"
import { CapsuleCollider, RigidBody, useRapier } from "@react-three/rapier"

const SPEED = 5
const direction = new THREE.Vector3()
const frontVector = new THREE.Vector3()
const sideVector = new THREE.Vector3()
const rotation = new THREE.Vector3()

export function Player({ lerp = THREE.MathUtils.lerp }) {

    const playerRef = useRef()
    const grounded = useRef(false);
    const [, get] = useKeyboardControls()
    const [targetHeight, setTargetHeight] = useState(0.7); // Target height for smooth transition
    const [height, setHeight] = useState(0.7); // Current height
    const lerpFactor = 0.1; // Adjust this value for smoother or faster transitions
 

    useFrame((state) => {
        const velocity = playerRef.current.linvel()       
        const { forward, backward, left, right, jump, crouch } = get()
        const translation = playerRef.current.translation();
        state.camera.position.set(translation.x, translation.y, translation.z);
  
        frontVector.set(0, 0, backward - forward)
        sideVector.set(left - right, 0, 0)
        direction.subVectors(frontVector, sideVector).normalize().multiplyScalar(SPEED).applyEuler(state.camera.rotation) 
        playerRef.current.setLinvel({ x: direction.x, y: velocity.y, z: direction.z })
        
        // if (jump && grounded.current) {
        //     playerRef.current.setLinvel({ x: 0, y: 7, z: 0 })
        //     grounded.current = false;
        // }
        
    })
    return (
        <>
            <RigidBody  ref={playerRef} colliders={false} mass={1} type="dynamic" position={[2, 2, 0]} enabledRotations={[false, false, false]} onCollisionEnter={(e) => {
                
                // if(e.rigidBodyObject.id === "181"){
                //     grounded.current = true
                // }
            }}>
                <CapsuleCollider args={[0.75, height]} />
            </RigidBody>
        </>
    )
}

我已经尝试过尽可能记录日志。与键盘控件关联的每个变量都起作用。当我按键时,前向和侧向矢量会发生变化。控制台也没有错误。

reactjs three.js react-three-fiber react-three-drei
1个回答
0
投票

我想我最近也遇到过类似的事情。

在 Typescript 中,一些 Rapier 方法除了 Vector 值之外还需要

wakeUp
bool 参数。

例如,在 TS 中,如果您希望

body.applyImpulse(impulse, true)
移动,您应该以这种方式施加脉冲
body

事情是

body
在几秒钟的延迟后进入睡眠状态(为了更好的性能),如果我发送
false
作为
wakeUp
参数,脉冲将不会被应用,瞌睡虫不会发生任何事情。

因此,除了矢量值之外,您可能还会尝试将

true
发送到
playerRef.current.setLinvel(vectorValue, true)

祝你好运😀

© www.soinside.com 2019 - 2024. All rights reserved.