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

THREE.js克隆对象属性联动问题:如何实现属性独立的克隆?

解决Three.js克隆OBJ对象后顶点颜色同步变化的问题

你推测的没错——Three.js中Object3D.clone()默认是浅克隆:克隆后的对象会共享原始对象的几何体(BufferGeometry)和材质引用,多个克隆体共用同一个几何体实例时,修改其中一个的顶点属性(比如颜色)会直接影响所有关联对象。

要实现完全独立的克隆,关键是让每个克隆体拥有独立的几何体副本,有两种可行方式:

方案一:克隆后手动创建独立几何体

在克隆原始对象后,遍历克隆体的所有Mesh,为每个Mesh克隆几何体:

// 递归克隆对象层级
const clonedTunnel = tunnels[0].clone(true);
// 遍历克隆体,为每个Mesh创建独立几何体
clonedTunnel.traverse(titem => {
  if (titem.isMesh) {
    // 克隆几何体,生成独立实例
    titem.geometry = titem.geometry.clone();
  }
});
// 后续修改位置、颜色等操作只影响当前克隆体
tunnels.push(clonedTunnel);

方案二:提前处理原始对象的几何体

在OBJ加载完成后,先为原始对象的Mesh克隆几何体,确保后续克隆时能基于独立副本生成:

oload.load("objects/tunnel1.obj", function(data)
{
    tunnels[0] = data;
    tunnels[0].traverse(function(titem)
    {
        if(titem.isMesh)
        {
            if(titem.name.toUpperCase().indexOf("INNER")>-1)
            {
                titem.material = new THREE.MeshBasicMaterial({map: wnewtex, vertexColors: true});
                // 提前克隆几何体,让原始对象使用独立实例
                titem.geometry = titem.geometry.clone();
            }
        }
    });
});

之后再调用.clone(true)克隆对象时,每个克隆体的Mesh会继承这个独立几何体的引用,修改颜色时不会互相干扰。

修正代码中的变量错误

你的代码里存在一处变量名错误:item.geometry.attributes.position.count应该改为titem.geometry.attributes.position.count,否则会导致无法正确获取顶点数量。

修改后的完整示例片段(以leveldata=23为例)

else if(leveldata[x][y] == 23)
{
    // 克隆对象并创建独立几何体
    const clonedTunnel = tunnels[0].clone(true);
    clonedTunnel.traverse(titem => {
        if (titem.isMesh) {
            titem.geometry = titem.geometry.clone();
        }
    });
    // 设置位置和旋转
    clonedTunnel.position.set(-x*2, newh, (height-y-1)*2);
    clonedTunnel.rotation.set(0, Math.PI/2, 0);
    // 修改顶点颜色
    clonedTunnel.traverse(function(titem)
    {
        if(titem.isMesh)
        {
            if(titem.name.toUpperCase().indexOf("INNER")>-1)
            {
                const vertexCount = titem.geometry.attributes.position.count;
                titem.geometry.setAttribute("color", new THREE.BufferAttribute(new Float32Array(vertexCount*3), 3));
                const colort = titem.geometry.attributes.color.array;
                for(let v2 = 0; v2 < vertexCount*3; v2+=3)
                {
                    colort[v2] = 1;
                    colort[v2+1] = 0;
                    colort[v2+2] = 0;
                }
                titem.geometry.attributes.color.needsUpdate = true;
            }
        }
    });
    tunnels.push(clonedTunnel);
    scene.add(clonedTunnel);
}

内容的提问来源于stack exchange,提问作者Edward

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:44:52