You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:31:07