如何在React Three Fiber中使角色在3D世界中移动



我正在React中制作一个小游戏,现在我正试图遍历我刚刚生成的三维世界。我正在使用React Three Fiber和其他一些实用程序库来帮助实现这一点。对于我的角色,我只是使用@react three/cannon中的球体对象,对于线性移动,我使用钩子来处理按键逻辑。出于某种原因,每当我加载应用程序时,我的按键都会被注册,但球体对象永远不会移动。为什么会发生这种情况?

App.jsx

import "./App.css";
import React from "react";
import { Canvas } from "@react-three/fiber";
import { Physics } from "@react-three/cannon";
import Lights from "./Components/Lights";
import { Camera } from "./Components/Camera";
import Ground from "./Components/Ground";
import CubeModel from "./Components/CubeModel";
import { Person } from "./Components/Person";
import { range } from "./helperMethods/range";
const matrix = [];
const matrixFactory = (
length: number,
width: number,
height: number,
scale = 2.5
) => {
if (length <= 0 || width <= 0 || height <= 0) {
throw new Error("Dimensions cannot be 0 or less");
}
let i = 0;
for (let x of range(0, length - 1)) {
for (let y of range(0, width - 1)) {
for (let z of range(0, height - 1)) {
let cartesianCoordinates = [x * scale, y * scale, z * scale];
matrix[i] = cartesianCoordinates;
i++;
}
}
}
};
function App() {
matrixFactory(4, 4, 6);
return (
<div className="App">
<Canvas>
<Lights />
<Camera />
<Physics gravity={[0, -30, 0]}>
<Ground position={[0, 0, 0]} />
<Person position={[-20, 3, 10]} />
<React.Suspense fallback={null}>
{matrix.map((value, idx) => (
<React.Fragment key={idx}>
<CubeModel
position={[value[0], value[1], value[2]]}
/>
</React.Fragment>
))}
</React.Suspense>
</Physics>
</Canvas>
</div>
);
}
export default App;

Person.jsx

import React from "react";
import { useSphere } from "@react-three/cannon";
import { useThree, useFrame } from "@react-three/fiber";
import { useKeyboardControls } from "../hooks/useKeyboardControls";
import { Vector3 } from "three";
const SPEED = 6;
export function Person(props) {
const { camera } = useThree();
const { moveForward, moveBackward, moveLeft, moveRight } =
useKeyboardControls();
const [ref, api] = useSphere(() => ({
mass: 1,
type: "Dynamic",
...props,
}));
const velocity = React.useRef([0, 0, 0]);
React.useEffect(() => {
api.velocity.subscribe((v) => (velocity.current = v));
}, [api.velocity]);
useFrame(() => {
camera.position.copy(ref.current.position);
const direction = new Vector3();
const frontVector = new Vector3(
0,
0,
Number(moveBackward) - Number(moveForward)
);
const sideVector = new Vector3(
Number(moveLeft) - Number(moveRight),
0,
0
);
direction
.subVectors(frontVector, sideVector)
.normalize()
.multiplyScalar(SPEED)
.applyEuler(camera.rotation);
api.velocity.set(direction.x, velocity.current[1], direction.z);
});
return (
<>
<mesh ref={ref} />
</>
);
}

使用KeyboardControls.js

import React from "react"
function actionByKey(key) {
const keys = {
KeyW: 'moveForward',
KeyS: 'moveBackward',
KeyA: 'moveLeft',
KeyD: 'moveRight'
}
return keys[key]
}
export const useKeyboardControls = () => {
const [movement, setMovement] = React.useState({
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false
})
React.useEffect(() => {
const handleKeyDown = (e) => {
// Movement key
if (actionByKey(e.code)) {
setMovement((state) => ({...state, [actionByKey(e.code)]: true}))
}
}
const handleKeyUp = (e) => {
// Movement key
if (actionByKey(e.code)) {
setMovement((state) => ({...state, [actionByKey(e.code)]: false}))
}
}
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);
return () => {
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('keyup', handleKeyUp);
}
}, [])
return movement
}

我知道答案很晚了,但我认为你应该加上"allowSleep:false";属性添加到您的useSphere,类型为:";"动态";例如

事实上,它允许球体永远不会被设置为"0";睡眠;基本上导致对象根本不移动的模式。

很高兴知道未来来这里的人

最新更新