Добавление 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
}
}