swift - 方法 `enumerateChildNodes` 未找到节点

标签 swift swiftui augmented-reality scenekit arkit

我正在开发一个具有 2 个按钮的 ARKit 应用程序:“播放”和“重置”。当我点击播放时,会显示一个金字塔节点。当我点击重置时,所有金字塔节点都应该从场景中删除:

enter image description here

另一个要求是我想在单击播放按钮时禁用它。

接下来是我的 contentView 代码:

import ARKit

struct ContentView: View {
    
    @State var node = SCNNode()
    @State var play: Bool = false
    @State var reset: Bool = false
    @State var isDisabled: Bool = false
    @State var showBanner:Bool = true
    
    var body: some View {
        ZStack {
            SceneKitView(node: $node, play: $play, reset: $reset, isDisabled: $isDisabled)
            VStack {
                Spacer()
                HStack {
                    Button(action: {
                        play = true
                    }) {
                        Image("Play")
                    }.padding()
                    .disabled(isDisabled) /// <<<<< THIS DISABLES THE BUTTON

                    Spacer()
                    
                    Button(action: {
                        play = false                        
                        reset = true
                    }) {
                        Image("Reset")
                    }.padding()
                }
            }
        }
    }
    
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

为了禁用“播放”按钮,我使用了 .disabled 和 bool 值 isDisabled

我的代码在 Coordinator 中将 isDisabled 的值更改为 TRUE :

import ARKit
import SwiftUI

struct SceneKitView: UIViewRepresentable {
    let arView = ARSCNView(frame: .zero)
    let config = ARWorldTrackingConfiguration()
    @Binding var node: SCNNode
    @Binding var play: Bool
    @Binding var reset: Bool
    @Binding var isDisabled: Bool
    
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    final class Coordinator: NSObject, ARSCNViewDelegate {
        var control: SceneKitView
        init(_ control: SceneKitView) {
            self.control = control
        }
        func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
            DispatchQueue.main.async {
                if self.control.play {
                    self.control.addNode()
                    self.control.play = false
                    self.control.isDisabled = true // HERE I UPDATE THE VALUE !!!!!!!!
                    self.control.reset = false
                }else{
                }
            }
        }
    }
    
    func removeNode(){
        self.arView.scene.rootNode.enumerateChildNodes { (node, _) in
            print("existing nodes = \(node)")
            node.removeFromParentNode()
        }
    }
    
    func updateUIView(_ uiView: ARSCNView,
     context: Context) {
        if self.reset {
            self.removeNode()
            print("game reseted")
        }
    }
    
    func makeUIView(context: Context) -> ARSCNView {
        arView.scene = SCNScene()
        arView.delegate = context.coordinator
        arView.autoenablesDefaultLighting = true
        //arView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
        arView.showsStatistics = true
        arView.session.run(self.config)
        return arView
    }
    
    func addNode(){
        let pyramid = SCNNode(geometry: SCNPyramid(width: 0.1, height: 0.1, length: 0.1))
        pyramid.geometry?.firstMaterial?.diffuse.contents = UIColor.red
        pyramid.geometry?.firstMaterial?.specular.contents = UIColor.white
        pyramid.position = SCNVector3(0,0,-0.5)
        self.arView.scene.rootNode.addChildNode(pyramid)
    }
    
}

问题:当应用程序正在运行并且我点击 RESET 时,方法 removeNode 被调用并且该方法使用 enumerateChildNodes 来查找节点并使用 removeFromParentNode 删除它们,但金字塔节点没有被删除! :(

(对我而言)最疯狂的是,如果我不更改 CoordinatorisDisabled 的值,即我注释那行,removeNode有效,节点被删除!!!!!

欢迎任何意见和建议:)

最佳答案

这解决了问题:

func updateUIView(_ uiView: ARSCNView, context: Context) {
    if self.reset {
        DispatchQueue.main.async {
            context.coordinator.control.removeNode()
            context.coordinator.control.isDisabled = false
        }
        print("Game Reset")
    }
}

关于swift - 方法 `enumerateChildNodes` 未找到节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68487509/

相关文章:

ios - Siren库如何获取当前的应用商店版本?

swift - 无法将类型 'Array<SKtexture>' 的值分配给类型 'SKTexture'

objective-c - Swift 中的飞利浦 HUE SDK

ios - 无法在此文件中预览 - [App Name].app 可能已在 Xcode 11 Beta 5 上崩溃

SwiftUI:显示警报时如何摆脱分段控制文本移动?

javascript - iPhone 12 Pro LiDAR API 访问 Safari

swift - spritekit如何有选择地缩放节点

javascript - AFrame - 是否可以用没有黑色边框的自定义图像替换标记?

ios - 为什么 ARFaceAnchor 有负 Z 位置?

ios - 按下后 SwiftUI Toggle 将被禁用