多次添加SCNNode只显示一次

Adding SCNNode multiple time shows only once

我正在尝试在不同位置的循环中添加 SCNNode 多次时间,但我可以在最后一个位置一次看到相同类型的节点。

代码如下

let entityArray:[entity] = [.coin, .coin, .coin, .brick, .coin, .coin, .coin, .brick]

func setupworld() {
    let scene = SCNScene(named: "art.scnassets/MainScene.scn")!

    var zPosition = -10
    var count = 0
    let delta = -4

    for entity in entityArray {

        var node = SCNNode()

        switch entity {
        case .coin:
            node = scene.rootNode.childNode(withName: "coin", recursively: true) ?? node
            node.position = SCNVector3(0, -5, zPosition)

        case .brick:
            node = scene.rootNode.childNode(withName: "brick", recursively: true) ?? node
            node.position = SCNVector3(0, 0, zPosition)
        }

        self.sceneView.scene.rootNode.addChildNode(node)

        zPosition += delta
        count += 1
    }
}

最后的位置显示一枚硬币和一块砖。

我是scenekit的新手所以会做错什么,请帮助我。

在其他评论的基础上,正如@rmaddy所说,SCNNode有一个clone()函数(这是你应该在这里采用的方法)并且简单地说:

Creates a copy of the node and its children.

然而,使用它时要注意的一件事是,每个 cloned Node 将共享相同的几何图形和 materials。

也就是说,如果您在任何时候想要一些红色的砖块和一些绿色的砖块,您将无法使用此方法来实现,因为:

changes to the objects attached to one node will affect other nodes that share the same attachments.

为了实现这个,例如要使用不同的 material 渲染节点的两个副本,您必须在分配新的 material 之前复制节点及其几何图形,您可以在此处阅读更多信息:Apple Discussion

你只看到硬币或砖块的一个实例的原因是每次你在循环中迭代时你都在说新创建的节点等于硬币或砖块,所以很自然该循环中的最后一个元素将是从您的场景中引用该元素的元素。

将其付诸实践并解决您的问题,您的 setupWorld function 应该如下所示:

/// Sets Up The Coins & Bricks
func setupworld(){

    //1. Get Our SCNScene
    guard let scene = SCNScene(named: "art.scnassets/MainScene.scn") else { return }

    //2. Store The ZPosition
    var zPosition =  -10

    //3. Store The Delta
    let delta = -4

    //4. Get The SCNNodes We Wish To Clone
    guard let validCoin = scene.rootNode.childNode(withName: "coin", recursively: true),
           let validBrick = scene.rootNode.childNode(withName: "brick", recursively: true) else { return }

    //5. Loop Through The Entity Array & Create Our Nodes Dynamically
    var count = 0

    for entity in entityArray {

        var node = SCNNode()

        switch entity{

        case .coin:
            //Clone The Coin Node
            node = validCoin.clone()
            node.position = SCNVector3(0, -5, zPosition)

        case .brick:
            //Clone The Brick Node
            node = validBrick.clone()
            node.position = SCNVector3(0, 0, zPosition)
        }

        //6. Add It To The Scene
        self.sceneView.scene.rootNode.addChildNode(node)

        //7. Adjust The zPosition
        zPosition += delta
        count += 1
    }

}