【问题标题】:Initialize materials on scene change in SceneKit (SwiftUI)在 SceneKit (SwiftUI) 中初始化场景变化的材质
【发布时间】:2020-08-25 09:28:39
【问题描述】:

我在我的 SwiftUI 应用程序中使用 SceneKit 来显示从 Blender 导出的 .dae 文件转换而来的一些 .scn 文件。

SceneKit 正在使用UIViewRepresentable 显示。

我正在显示分步指导指南,每个步骤都包含一些文本和动画。每个动画都有自己的.scn 文件,我正在根据当前步骤交换场景文件。

我的问题是当场景被交换时我需要对材质进行一些初始化,但是当这种情况发生时只调用updateUIView,我不想在这里做这项工作,因为每次动画都会调用它已暂停等。

我想在每次更换场景时都做一次这项工作,但我正在努力用我当前的实现找到解决方案。

我认为我处理此场景交换的方式不正确,但我想知道是否有人可以指出正确的方向。

谢谢!

查看下面的完整代码:

struct MaintenanceFlowDetailView: View {

    var maintenanceFlow: MaintenanceFlow
    @State private var currentStepIndex = 0
    @State private var pauseAnimation = false

    func stepBackwards() {
        currentStepIndex -= 1
        pauseAnimation = false
    }

    func stepForwards() {
        currentStepIndex += 1
        pauseAnimation = false
    }

    func togglePauseAnimation() {
        pauseAnimation = !pauseAnimation
    }

    var body: some View {
        NavigationView{
            VStack(alignment: .leading, spacing: 12){
                SceneKitView(sceneFilePath: maintenanceFlow.steps[currentStepIndex].scenePath, pauseAnimation: $pauseAnimation)
                    .frame(height: 300)
                Text(maintenanceFlow.steps[currentStepIndex].text)
                Spacer()
                HStack{
                    if currentStepIndex > 0 {
                        Button(action: stepBackwards) {
                            Text("Back")
                        }
                    }
                    Spacer()
                    Button(action: togglePauseAnimation) {
                        Text(pauseAnimation ? "Play" : "Pause")
                    }
                    Spacer()
                    if currentStepIndex < maintenanceFlow.steps.count - 1 {
                        Button(action: stepForwards) {
                            Text("Next")
                        }
                    }

                }
            }.padding()
            .navigationBarTitle(Text(maintenanceFlow.name))
        }

    }
}

struct SceneKitView : UIViewRepresentable {

    var sceneFilePath: String
    @Binding var pauseAnimation: Bool

    func makeUIView(context: Context) -> SCNView {

        print("calling CREATE view")

        // I NEED TO INITIALISE MATERIALS ETC JUST ONCE HERE...

        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        print("calling UPDATE view")

        // BUT THE SCENE IS REPLACED HERE :(

        let scene = SCNScene(named: sceneFilePath)!
        scene.isPaused = pauseAnimation
        scnView.scene = scene

        scnView.showsStatistics = true
    }
}

【问题讨论】:

    标签: ios swift swiftui scenekit


    【解决方案1】:

    使用以下内容:

    struct SceneKitView : UIViewRepresentable {
    
        var sceneFilePath: String
        @Binding var pauseAnimation: Bool
    
        func makeUIView(context: Context) -> SCNView {
    
            print("calling CREATE view")
    
            let scnView = SCNView()
            let scene = SCNScene(named: sceneFilePath)
    
            scnView.scene = scene
            scnView.showsStatistics = true
            return scnView
        }
    
        func updateUIView(_ scnView: SCNView, context: Context) {
            print("calling UPDATE view")
            scnView.scene?.isPaused = pauseAnimation
        }
    }
    

    更新:有点修正,但想法是一样的。使用 Xcode 11.4 / iOS 13.4 测试。 SceneKitView 是在sceneFilePath: 改变时重新创建的,所以如果它没有更新,那么它是不同的代码问题。

    这是使用的测试视图:

    struct TestSceneKitView: View {
        @State private var filePath = "test1"
        var body: some View {
            VStack {
                Button("Push") { self.filePath = "test2" }
                SceneKitView(sceneFilePath: filePath, pauseAnimation: .constant(false))
            }
        }
    }
    

    【讨论】:

    • 感谢@Asperi 的回答。但是,现在这会导致在更改索引时不会切换场景。
    • 感谢您的编辑。我已经复制并粘贴了您的新代码,单击 Push 时仅打印“调用 UPDATE 视图”。您是否看到打印了“调用 CREATE 视图”??
    • @Tappyy。是的,我愿意。
    • 我运行的是 Xcode 11.3,所以我更新到 11.4.1,但仍然没有运气。我将您的代码复制到它自己的文件和调试预览中,单击推送时仍然只看到“调用更新视图”:/
    猜你喜欢
    • 2014-12-07
    • 2021-08-26
    • 2017-02-03
    • 1970-01-01
    • 2020-07-12
    • 2020-10-24
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多