如何在three.js或react-three-fiber中多次渲染同一个GLTF模型不被覆盖
问题原因
Three.js 中的Object3D实例(包括GLTF加载出来的scene对象)同一时间只能挂载到场景的一个父节点下。react-three-fiber的useLoader会缓存加载完成的GLTF资源,两次调用<Door />组件时拿到的是同一个gltf.scene实例,第二次渲染时该实例会被直接移动到第二扇门的配置位置,第一扇门自然就消失了。
解决方案
方案一:克隆GLTF场景实例(快速修改)
每次渲染门时对缓存的gltf.scene做深克隆,保证每扇门都是独立的实例,几何体和材质会自动复用,不会额外增加太多性能开销。仅需修改Door.tsx:
import React from 'react'; import { useLoader } from "@react-three/fiber"; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; interface DoorProps { rotation: any; // 建议把position也改成可配置的,避免两扇门位置重叠 position?: [number, number, number]; } function Door(props: DoorProps) { const gltf = useLoader(GLTFLoader, '/simple_door.gltf'); // 深克隆场景实例,true代表克隆所有子节点 const doorScene = gltf.scene.clone(true); return ( <primitive object={doorScene} position={props.position ?? [25, 1, -17]} scale={0.05} rotation={props.rotation} /> ); } export default Door;
方案二:转成原生R3F组件(更适合后续扩展)
如果后续需要给门加交互、修改局部样式,更推荐用gltfjsx工具把GLTF模型直接生成React Three Fiber组件,生成的组件每次渲染默认就是独立实例,不会出现挂载冲突,还能直接操作内部的网格、材质属性。使用方式为命令行执行npx gltfjsx simple_door.gltf,即可生成对应的Door组件文件,直接导入使用即可。
内容的提问来源于stack exchange,提问作者Tom Vu
相关产品推荐
相关产品推荐

