THREE.Object3D.add错误求助:非THREE.Object3D实例问题排查
THREE.Object3D.add 错误排查与解决
问题详情
- 编程新手,跟着YouTube教程学习Three.js,出现错误:
THREE.Object3D.add: object not an instance of THREE.Object3D - 已3年未接触编程,跟着教程操作仍有难度,调试后无法解决问题
- 查帖得知常见方案是导入时添加
.scene,但不确定是Resources.js的问题还是整体代码错误
附相关代码与截图
Resources.js 代码
import * as THREE from "three"; import { EventEmitter } from "events"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js"; import Experience from "../Experience.js"; export default class Resources extends EventEmitter{ constructor(assets){ super(); this.experience = new Experience(); this.renderer = this.experience.renderer; this.assets = assets; this.items = {}; this.queue = this.assets.length; this.loaded = 0; this.setLoaders(); this.startLoading(); } setLoaders() { this.loaders = {}; this.loaders.gltfLoader = new GLTFLoader(); this.loaders.dracoLoader = new DRACOLoader(); this.loaders.dracoLoader.setDecoderPath("/draco/"); this.loaders.gltfLoader.setDRACOLoader(this.loaders.dracoLoader); } startLoading() { for (const asset of this.assets){ if(asset.type === "glbModel") { this.loaders.gltfLoader.load(asset.path, (file)=> { this.singleAssetLoaded(asset, file); }); }else if (asset.type === "videoTexture"){ this.video = {}; this.videoTexture = {}; this.video[asset.name] = document.createElement("video"); this.video[asset.name].src = asset.path; this.video[asset.name].muted = true; this.video[asset.name].playsInLine = true; this.video[asset.name].autoplay = true; this.video[asset.name].loop = true; this.video[asset.name].play(); this.videoTexture[asset.name] = new THREE.VideoTexture(this.video[asset.name]); this.videoTexture[asset.name].flipY = true; this.videoTexture[asset.name].minFilter = THREE.NearestFilter; this.videoTexture[asset.name].magFilter = THREE.NearestFilter; this.videoTexture[asset.name].generateMipmaps = false; this.videoTexture[asset.name].encoding = THREE.sRGBEncoding; this.singleAssetLoaded(asset, this.videoTexture[asset.name]); } } } singleAssetLoaded(asset, file) { this.items[asset.name] = file; this.loaded++; if(this.loaded === this.queue){ this.emit("ready"); } } }
ENVIRONMENT.JS 截图

解决方案
这个错误的核心是:你尝试添加到场景/组中的对象不是Three.js的Object3D实例。结合你的代码,问题出在GLB模型的加载处理上:
- GLTFLoader加载完成后返回的
file是一个GLTF对象,只有它的.scene属性才是可添加到场景的THREE.Object3D实例 - 你当前的代码直接把整个GLTF对象存在了
this.items里,后续在Environment.js中直接用这个对象调用add,自然会触发错误
具体修改步骤
- 修改
Resources.js中GLB模型的加载回调,传递file.scene而非整个GLTF对象:
// 原代码 this.loaders.gltfLoader.load(asset.path, (file)=> { this.singleAssetLoaded(asset, file); }); // 修改后 this.loaders.gltfLoader.load(asset.path, (file)=> { this.singleAssetLoaded(asset, file.scene); });
- 如果后续需要GLTF对象中的其他资源(比如材质、动画剪辑),可以把整个GLTF对象一起存储:
// 在singleAssetLoaded里修改存储逻辑 singleAssetLoaded(asset, file) { if(asset.type === "glbModel"){ this.items[asset.name] = { scene: file.scene, gltf: file }; } else { this.items[asset.name] = file; } this.loaded++; if(this.loaded === this.queue){ this.emit("ready"); } }
之后在使用模型时,取xxx.scene来添加到场景即可。
- 同时检查Environment.js中的代码,确保你调用
add方法时传入的是模型的scene对象,而非原始的GLTF加载结果。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

