我有一个使用 react-three-fiber 的第三人称游戏,我想在玩家移动的任何地方添加一种尾灯效果。光迹会在一段时间后消失,所以我想为这些点设置一个固定大小的数组。这是我最初尝试的解决方案:
const point = new THREE.Vector3();
const points = new Array(50).fill(null).map(p => new THREE.Vector3());
let index = 0;
const Trail = () => {
const ref = useRef();
const playerBody = useStore(state => state.player); // contains player position
const [path, setPath] = useState(new THREE.CatmullRomCurve3(points));
useFrame(() => { // equivalent to raf
const { x, y, z } = playerBody.position;
point.set(x, y, z);
points[index].copy(point);
index = (index + 1) % 50;
setPath(new THREE.CatmullRomCurve3(points));
if (ref && ref.current) {
ref.current.attributes.position.needsUpdate = true;
ref.current.computeBoundingSphere();
}
});
return (
<mesh>
<tubeBufferGeometry ref={ref} attach="geometry" args={[path, 20, .5, 8, false]} />
<meshBasicMaterial attach="material" color={0xffffff} />
</mesh>
)
}
基本上,我的思考过程是更新每一帧(或每 x 帧以提高性能)上的曲线,并使用索引来跟踪要更新的点数组中的哪个位置。
但是我遇到了两个问题:
- TubeBufferGeometry 不更新。不确定是否可以在实例化后更新几何。
- 我预见到使用这种固定数组/索引方法的缺陷是,一旦我到达数组的末尾,我将不得不绕回索引 0。所以曲线插值会搞砸,因为我假设它需要点依次。数组中的最后一个点现在应该连接到第一个点,但不会那样。
为了解决#2,我尝试了类似
points.unshift();
points.push(point.clone);
而不是,points[index].copy(point);
但我仍然无法让 Tube 首先更新。
我想看看是否有更好的解决方案,或者这是否是解决此类问题的正确方法。