Swift 多次添加SCNNode只显示一次

Swift 多次添加SCNNode只显示一次,swift,scenekit,arkit,scnnode,scnscene,Swift,Scenekit,Arkit,Scnnode,Scnscene,我试图在不同位置的循环中添加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

我试图在不同位置的循环中添加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()
函数(这是您在这里应该采取的方法),它只是:

创建节点及其子节点的副本

但是,使用此选项时需要注意的一点是,每个
克隆节点将共享相同的几何体和材质

这就是说,如果你想在任何时候拥有一些红色的砖块和一些绿色的砖块,你都无法使用这种方法,因为:

对附着到一个节点的对象所做的更改将影响 共享相同附件的其他节点

要实现这一点,例如,要使用不同材质渲染节点的两个副本,必须先复制节点及其几何体,然后才能指定新材质,您可以在此处阅读更多有关内容:

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

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

/// 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
    }

}

在其他评论的基础上,正如@rmaddy所说,
SCNNode
有一个
clone()
函数(这是您在这里应该采取的方法),它只是:

创建节点及其子节点的副本

但是,使用此选项时需要注意的一点是,每个
克隆节点将共享相同的几何体和材质

这就是说,如果你想在任何时候拥有一些红色的砖块和一些绿色的砖块,你都无法使用这种方法,因为:

对附着到一个节点的对象所做的更改将影响 共享相同附件的其他节点

要实现这一点,例如,要使用不同材质渲染节点的两个副本,必须先复制节点及其几何体,然后才能指定新材质,您可以在此处阅读更多有关内容:

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

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

/// 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
    }

}

您是否尝试给它们不同的“名称”?您不断地添加相同的节点。一个节点只能添加一次。我对SceneKit几乎一无所知,但在
SCNNode
上有一个
clone
功能。我仔细看了一件事,我想你应该使用新初始化的节点来设置和添加,就像@rmaddy说的,你不应该再次使用同一个节点,正确的方法是使用您初始化的方法并正确配置它。var node=SCNNode()进行初始化,问题是:node=scene.rootNode.childNode(名称为“coin”,递归为:true)??节点您每次都检索现有节点…您是否尝试给它们不同的“名称”?您不断地添加相同的节点。一个节点只能添加一次。我对SceneKit几乎一无所知,但在
SCNNode
上有一个
clone
功能。我仔细看了一件事,我想你应该使用新初始化的节点来设置和添加,就像@rmaddy说的,你不应该再次使用同一个节点,正确的方法是使用您初始化的方法并正确配置它。var node=SCNNode()进行初始化,问题是:node=scene.rootNode.childNode(名称为“coin”,递归为:true)??节点您每次都检索现有节点…感谢您编辑我的代码并解释一切:)很高兴它有帮助:)感谢您编辑我的代码并解释一切:)很高兴它有帮助:)