@react-three / react-three-fiber: useLoader() 在 props 改变时加载新文件

@react-three / react-three-fiber: useLoader() to load new file on props change

我有一个功能性的 React 组件和一个 gltf 模型的初始加载 - 路径通过道具传递 - 这工作正常。

但是如果 props 更改组件重新渲染 - 我检查过 - 路径已更改并且应该加载新模型 - 但我没有。

如何才能做到这一点? 我想 swap/replace 状态更新时正在渲染的对象。

我尝试了不同的加载程序,将 gltf 自身设置为一个状态,但是 none 这个 wokred。我想我错过了一个基本概念。请帮忙

  function Character(props) {
      const spinner = useRef();
      console.log(props.model, "from modelpreviewer");
      const gltf = useLoader(GLTFLoader, props.model);
    
      return gltf ? (
        <primitive
          ref={spinner}
          object={gltf.scene}
        />
      ) : null;
    }

角色组件是这样渲染的:

<Canvas
   camera={{ position: [0, 0, 10] }}>
    <ambientLight intensity={0.8} />
    <spotLight intensity={0.7} position={[300, 300, 400]} />
    <Suspense fallback={null}>
      <Character model={props.model} />
    </Suspense>
  </Canvas>

我在渲染纹理时测试了 useLoader 的问题,它对我来说工作正常。 这是一个简单的 example,显示每当 props 改变时纹理都会改变。

我猜你错过了指向 props.model 的正确路径。也许您可以硬编码 props.model 的值以确保文件路径正确与否。

已编辑

我找到了 gltf 只渲染一次的原因。答案是here.

You can't reuse meshes or put the same object into the scene twice in webgl/threejs, it will just unmount and remount.

另一种解决方案是 clone the scene

const { scene } = useLoader(GLTFLoader, url)
const copiedScene = useMemo(() => scene.clone(), [scene])

我也在codesandbox上提供了一个固定的例子。