Возможно ли изменить объект сцены ARKit при нажатии на кнопку Swift

#swift #augmented-reality #arkit #scnscene #arscnview

#swift #дополненная реальность #arkit #scnscene #arscnview

Вопрос:

Я впервые создаю проект ARKit, и что мне нужно сделать, это, прежде всего, отобразить 3D-сферу в ARSCNView. и затем, когда я нажимаю на кнопку, сфера должна исчезнуть и на ее месте отобразиться 3D-куб.

Я думал об этом объявлении, что мой код :

  @IBOutlet weak var sceneView: ARSCNView!
    var  objectNode: SCNNode?
    var objectScene: SCNScene?

objectScene = SCNScene(named: "sphere.dae")
objectNode = objectScene!.rootNode
sceneView.scene.rootNode.addChildNode(objectNode!)
  

и вот код для кнопки:

 @IBAction func cubeButtonClicked(_ sender: UIButton) {
          sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
            node.removeFromParentNode()
        }
        
        objectScene = SCNScene(named: "cube.dae")    
        objecteNode = objectScene!.rootNode
        sceneView.scene.rootNode.addChildNode(objecteNode!) 
    }
    
  

и я сталкиваюсь с этой ошибкой

 [SceneKit] Error: removing the root node of a scene from its scene is not allowed
  

Я делаю что-то не так?

Ответ №1:

На самом деле ошибка точно указывает, что ее вызывает.

Отредактировано — попробуйте один из двух следующих способов

  • Используйте следующий код, чтобы избежать удаления, pointOfView который является вашим SCNCamera .
 sceneView.scene.rootNode.enumerateChildNodes { (node, _) in
    if node == sceneView.pointOfView {return}
    node.removeFromParentNode()
}
  
  • Если у вас есть только один узел для удаления, который в вашем случае является sphereNode , нет необходимости использовать метод enumerate . Просто удерживайте ссылку на этот узел и удаляйте, если захотите.
 sphereNode.removeFromParentNode()
  

Комментарии:

1. Спасибо за ваш ответ @kevinn-w, но на самом деле это не решает мою проблему, я все еще ищу решение

2. Привет @Elin, можешь ли ты попробовать два метода в моем обновленном ответе?

3. Привет @Kevinn W, спасибо за вашу помощь, я действительно разобрался со своей проблемой. а именно: я пытался добавить новый узел до того, как другой будет удален, поскольку функция удаления в into a closure является асинхронной задачей, поэтому я добавил некоторый код, чтобы функциональность добавления заработала сразу после завершения работы закрытия. это имеет смысл, не так ли?

4. Да, @Elin. Вам действительно нужно убедиться, что узел удален, прежде чем добавлять новый материал. Мне любопытно, почему вы должны использовать enumerated , разве вы не можете просто удалить этот узел перед созданием нового узла?

Ответ №2:

Чего мне не хватало в моем приведенном выше коде, так это того, что мне пришлось выполнить удаление и добавить две задачи синхронизации. Поскольку функция удаления находится в закрытии (асинхронная задача). таким образом, функция добавления будет выполнена перед удалением. И к тому времени ошибка исчезнет.