Добавление SCNNode несколько раз показывает только один раз

Я пытаюсь добавить 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, поэтому буду делать что-то не так, пожалуйста, помогите мне.

1 ответ

Решение

Основываясь на других комментариях и, как сказал @rmaddy, SCNNode имеет clone() функция (какой подход вы должны использовать здесь) и который просто:

Создает копию узла и его дочерних элементов.

Однако следует помнить, что при использовании этого cloned Node будет иметь одинаковую геометрию и материалы.

То есть, если вы хотите, чтобы в любой момент были кирпичи красного цвета, а некоторые зеленого цвета, вы не смогли бы сделать это с помощью этого метода, поскольку:

изменения в объектах, прикрепленных к одному узлу, будут влиять на другие узлы, которые имеют одинаковые вложения

Для этого, например, для рендеринга двух копий узла с использованием разных материалов, вы должны скопировать как узел, так и его геометрию, прежде чем назначать новый материал, о котором вы можете прочитать подробнее здесь: Обсуждение Apple

Причина, по которой вы видите только один экземпляр монеты или кирпича, заключается в том, что каждый раз, когда вы повторяете цикл, вы говорите, что вновь созданный узел равен монете или кирпичу, поэтому, естественно, последний элемент в этом цикл будет ссылаться на этот элемент из вашей сцены.

Применяя это на практике и решая вашу проблему, ваши 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
    }

}
Другие вопросы по тегам