Three.js v0.91带材质深度克隆失效,原v0.79自定义方法无法使用
解决Three.js v0.91中网格带材质深度克隆失效的问题
嘿,我来帮你搞定这个版本升级后的克隆问题!你在v0.79里写的自定义克隆方法失效,核心原因是Three.js从v0.86开始对Object3D和Mesh的clone()逻辑做了大改动——旧版本允许你传自定义对象当克隆模板,新版本直接砍掉了这个参数,而且材质克隆的默认行为也变了,默认只会引用原材质,不会深度复制。
给你两个靠谱的解决方案:
方案1:重新实现原型方法(适配新版本)
我调整了你的原型方法,用新版本的API来实现完整的深度克隆(包括材质):
THREE.Object3D.prototype.GdeepCloneMaterials = function() { // 先做基础克隆,不递归,我们自己处理层级遍历 const clonedObject = this.clone(false); // 遍历原对象的所有子元素,逐个处理克隆 this.traverse((child) => { if (child instanceof THREE.Mesh) { // 克隆Mesh的几何体+深度克隆材质 const clonedMesh = child.clone(false); clonedMesh.geometry = child.geometry.clone(); // 这里的true是关键,会深度克隆材质的所有属性(纹理、uniforms之类的) clonedMesh.material = child.material.clone(true); // 把克隆后的Mesh加到对应的父层级里 const parentInClone = clonedObject.getObjectById(child.parent.id); if (parentInClone) { parentInClone.add(clonedMesh); } } else if (child instanceof THREE.Object3D && child !== this) { // 非Mesh的对象直接基础克隆后加入对应层级 const clonedChild = child.clone(false); const parentInClone = clonedObject.getObjectById(child.parent.id); if (parentInClone) { parentInClone.add(clonedChild); } } }); return clonedObject; };
方案2:不用改原型,直接写工具函数
如果你不想污染Three.js的原型链,也可以写个独立工具函数,先默认克隆再替换材质:
function deepCloneWithMaterials(originalObj) { // 先递归克隆整个对象结构(默认只会引用原材质) const clonedObj = originalObj.clone(true); // 遍历克隆后的对象,把所有Mesh的材质换成深度克隆版 clonedObj.traverse((child) => { if (child instanceof THREE.Mesh) { child.material = child.material.clone(true); } }); return clonedObj; } // 用的时候直接调用就行 const myClonedGroup = deepCloneWithMaterials(yourOriginalMeshGroup);
划重点:
material.clone(true)里的true一定要加,不然只会浅克隆材质(比如纹理还是引用原来的,改克隆后的材质会影响原对象)- 新版本用
traverse()遍历所有子对象比手动循环children靠谱多了,能适配各种嵌套结构 - 现在Three.js的默认
clone(true)已经会递归克隆所有子对象了,我们只需要额外处理材质的深度克隆就行
内容的提问来源于stack exchange,提问作者Chicken-Island LWOS
相关产品推荐
相关产品推荐

