Swift 更改子节点的颜色

Swift 更改子节点的颜色,swift,ios8,scenekit,Swift,Ios8,Scenekit,当前,当我更改子节点的颜色时,它将导致所有其他子节点的颜色更改,这是我不希望看到的 我通过以下方式更改子节点的颜色: let materials = node.geometry?.materials as! [SCNMaterial] let material = materials[0] material.diffuse.contents = UIColor.grayColor() 默认情况下,如果有多个节点分配了相同的scngometry实例,则这些节点也具有相同的材质。更改材质会更改使用

当前,当我更改子节点的颜色时,它将导致所有其他子节点的颜色更改,这是我不希望看到的

我通过以下方式更改子节点的颜色:

let materials = node.geometry?.materials as! [SCNMaterial]
let material = materials[0]
material.diffuse.contents = UIColor.grayColor()

默认情况下,如果有多个节点分配了相同的
scngometry
实例,则这些节点也具有相同的材质。更改材质会更改使用该材质的所有节点的外观

scngometry
对象并不直接表示几何数据-它实际上只是一组几何数据和一组材质之间关联的轻量级表示。因此,如果要在多个节点上使用不同材质渲染相同的几何体,只需复制几何体对象。。。它们仍将共享底层数据,因此渲染时间成本可以忽略不计,但您可以独立更改它们的材质

复制几何图形后,可以独立更改两个几何图形上的材质集,但这些材质集仍共享相同的
scnmatary
实例。(这很有用,因为一个几何体可以有多个材质,而每个材质都是多个属性的集合,因此尽可能高效地共享它们。)因此,可以为每个几何体指定新材质,也可以取消共享材质

// Using copy as a way to get two nodes with the same material
// (but your scene might already have two such nodes)
let node2 = node1.copy() as! SCNNode 

// Right now, node2 is sharing geometry. This changes the color of both:
node1.geometry?.firstMaterial?.diffuse.contents = UIColor.redColor()

// Un-share the geometry by copying
node2.geometry = node1.geometry!.copy()
// Un-share the material, too
node2.geometry?.firstMaterial = node1.geometry!.firstMaterial!.copy() as? SCNMaterial
// Now, we can change node2's material without changing node1's:
node2.geometry?.firstMaterial?.diffuse.contents = UIColor.blueColor()
2014年世界野生动植物保护大会的演讲中对此进行了很好的讨论。视频中的37:15左右或PDF中的第159张幻灯片上有相关信息。

根据评论和代码,下面是现成的答案:

// Un-share the geometry by copying
node.geometry = node.geometry!.copy() as? SCNGeometry
// Un-share the material, too
node.geometry?.firstMaterial = node.geometry?.firstMaterial!.copy() as? SCNMaterial
// Now, we can change node's material without changing parent and other childs:
node.geometry?.firstMaterial?.diffuse.contents = UIColor.blueColor()

现在已经简化了

    let searchNode = node.childNode(withName: "YOUR_CHILD_NODE_NAME", recursively: true)
    searchNode?.geometry?.firstMaterial?.diffuse.contents = UIColor.red

在这里,它搜索完整的树。子节点、子节点等,直到找到具有特定名称的节点。

您是否碰巧使用了共享几何体?这可以解释一个节点上的颜色更改会更改其他节点上的颜色这一事实。您可能需要尝试取消共享几何体,然后取消共享材质。@sambro我使用的是来自的汽车模型。我不知道它是否是共享几何体。我正在尝试更改控制盘的颜色,而控制盘是此文件中的子节点。不幸的是,这不起作用。可能是因为node1应该被node2取代,但我不知道该怎么做。我已经在操场上使用了这个精确的代码。。。您可能希望确保添加到场景中的内容是您期望的
node1
node2
?澄清一下:您是否使用了github.com/jamesfolk/scenekittvehicledemo中的
汽车模型。
?我想做的是改变汽车轮子的颜色。这个示例代码最初来自苹果,顺便说一句-看看原始下载和苹果将来在那里的任何更新。要在那个场景中启动轮子,你有两个问题:首先,你需要抓住正确的节点,而不是汽车本身,但是其中一个节点持有车轮几何体(在场景中命名为
WheelRear
)。其次,模型在装运示例中的显示方式,由于纹理贴图,轮胎和车轮内部看起来不同,因此您无法通过指定纯色材质来保持这种效果。但您应该能够抓取其中一个控制盘节点,取消其几何体和材质的共享,并为其指定纯色。