停止以编程方式与其克隆共享节点的几何图形

Stop sharing node's geometry with its clone programmatically

当您创建对象的副本时,几何体及其属性 (materials...) 将与该对象共享。
在 Xcode 场景编辑器中,您可以通过将 Geometry Sharing(在 Attributes Inspector 下)设置为 Unshare 可以轻松禁用它。

我想以编程方式实现相同的功能,但在 SceneKit 文档中找不到任何类似的属性。
我找到了一个类似的 post,其中有人建议复制对象,它的几何形状和它的 material。我尝试这样做但没有成功。

这是我代码的相关部分:

let randomColors: [UIColor] = [UIColor.blue,  UIColor.red,  UIColor.yellow,  UIColor.gray]
let obstacleScene = SCNScene(named: "art.scnassets/Scenes/obstacleNormal.scn")
let obstacle = obstacleScene?.rootNode.childNode(withName: "obstacle", recursively: true)

for i in 1...15 {
    let randomPosition = SCNVector3(x: Float(i) * 3.5, y: 0.15, z: sign * Float(arc4random_uniform(UInt32(Int(playgroundZ/2 - 2.0))) + 1))
    let randomColor = randomColors[Int(arc4random_uniform(UInt32(3)))]

    let obstacleCopy = obstacle?.clone()
    obstacleCopy?.position = randomPosition
    obstacleCopy?.geometry?.materials.first?.diffuse.contents = randomColor
    obstacleCopy?.eulerAngles = SCNVector3(x: 10.0 * Float(i), y: Float(30 - i), z: 5.0 * Float(i) * sign) //malo na random

    obstacleCopy?.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
    obstacleCopy?.physicsBody?.isAffectedByGravity = false
    obstacleCopy?.physicsBody?.categoryBitMask = PhysicsCategory.obstacle
    obstacleCopy?.physicsBody?.collisionBitMask = PhysicsCategory.none
    obstacleCopy?.physicsBody?.contactTestBitMask = PhysicsCategory.car1 | PhysicsCategory.car2 | PhysicsCategory.barrier

    obstacleArray.append(obstacleCopy!)
    raceScene!.rootNode.addChildNode(obstacleCopy!)
}

我想在这些对象上设置不同的属性但不能,因为它们的几何形状是共享的。
我尝试通过复制对象并克隆它来实现这一点,但我看不出有任何区别复制或克隆它。

有没有属性可以实现几何体取消共享,类似于场景编辑器中的选项,或者应该也是复制对象几何体的方法及其 material 的工作?

根据clone() API reference,您可以在克隆后复制几何体,这将为您的节点创建一个新的非共享几何体。

let newNode = node.clone()
newNode.geometry = node.geometry?.copy() as? SCNGeometry

附加到复制几何体的 material 与原始几何体上使用的相同,因此任何更改仍会影响两者。 要么创建一个新的 material,要么制作一个副本。

if let newMaterial = newNode.geometry?.materials.first.copy() as? SCNMaterial {
    //make changes to material
    newNode.geometry?.materials = [newMaterial]
}

您可以深度克隆一个 SCNNode,它会创建一个与原始对象不共享的几何体和不共享的材质。

fileprivate func deepCopyNode(node: SCNNode) -> SCNNode {
    let clone = node.clone()
    clone.geometry = node.geometry?.copy() as? SCNGeometry
    if let g = node.geometry {
        clone.geometry?.materials = g.materials.map{ [=10=].copy() as! SCNMaterial }
    }
    return clone
}