ios - 如何在 SwiftUI 中使用 "*.scnp"文件进行按钮单击(iOS)?

标签 ios swiftui scenekit

我有 "Explode.scnp" SceneKit文件。它已经配置好了,纹理已经设置好了。

我们如何在 SwiftUI 中使用它?
例如,单击按钮后,背景将动画一次。

var body: some View {
    ZStack {
            VStack {
                Button(action: {
                  Particles()
                }) { 
                  Text("Animate")
                }
            }
     }
}

此代码适用于 scn。但是如何将它与 scnp 一起使用?
import SwiftUI
import SceneKit

struct ScenekitView : UIViewRepresentable {
    let scene = SCNScene(named: "art.scnassets/ship.scn")!

    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black
    }
}

#if DEBUG
struct ScenekitView_Previews : PreviewProvider {
    static var previews: some View {
        ScenekitView()
    }
}
#endif

此外,Xcode 版本是 11.3.1。
当我尝试创建一个新文件时,我有这个:
enter image description here

扩展名是SKS ...有什么想法吗?

根据@Asperi 版本重新编写代码:
import SwiftUI
import SceneKit

struct ScenekitView : UIViewRepresentable {
    @Binding var exploding: Bool
    //let scene = SCNScene(named: "SceneKit.scnassets/Explode.scnp")!
    let scene = SCNScene(named: "SceneKit.scnassets/scene.scn")!

    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "blow", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black

        if exploding {
            if let scene = scene.rootNode.childNode(withName: "SceneKit.scnassets/scene", recursively: false),
                let particles = SCNParticleSystem(named: "SceneKit.scnassets/Explode", inDirectory: nil) {

                let node = SCNNode()
                node.addParticleSystem(particles)
                node.position = scene.position
                scnView.scene?.rootNode.addChildNode(node)
                scene.removeFromParentNode()
            }
        }
    }
}

与路径名相关的错误...
// retrieve the ship node

这里。尝试过 .sks、.scnp ... 有什么想法吗?

最佳答案

这是带有演示的修改代码。使用 Xcode 11.4/macOS 10.15.4 测试

demo

注意:由于我不知道您的项目结构,所有依赖的资源文件都被添加为资源(不在 Assets 中)。以防万一。

resources

struct DemoSceneKitParticles: View {
    @State private var exploding = false
    var body: some View {
        VStack {
            ScenekitView(exploding: $exploding)
            Button("BOOM") { self.exploding = true }
        }
    }
}

struct ScenekitView : NSViewRepresentable {
    @Binding var exploding: Bool
    let scene = SCNScene(named: "ship.scn")!

    func makeNSView(context: NSViewRepresentableContext<ScenekitView>) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = NSColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateNSView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = NSColor.black

        if exploding {
            if let ship = scene.rootNode.childNode(withName: "ship", recursively: true),
                let particles = SCNParticleSystem(named: "Explosion", inDirectory: nil) {

                let node = SCNNode()
                node.addParticleSystem(particles)
                node.position = ship.position
                scnView.scene?.rootNode.addChildNode(node)
                ship.removeFromParentNode()
            }
        }
    }
}

更新:iOS 的变体

使用 Xcode 11.4/iOS 13.4 测试

demo3

完整的模块代码(资源文件和以前一样在顶层)
import SwiftUI
import SceneKit

struct DemoSceneKitParticles: View {
    @State private var exploding = false
    var body: some View {
        VStack {
            ScenekitView(exploding: $exploding)
            Button("BOOM") { self.exploding = true }
        }
    }
}

struct ScenekitView : UIViewRepresentable {
    @Binding var exploding: Bool
    let scene = SCNScene(named: "ship.scn")!

    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black

        if exploding {
            if let ship = scene.rootNode.childNode(withName: "ship", recursively: true),
                let particles = SCNParticleSystem(named: "Explosion", inDirectory: nil) {

                let node = SCNNode()
                node.addParticleSystem(particles)
                node.position = ship.position
                scnView.scene?.rootNode.addChildNode(node)
                ship.removeFromParentNode()
            }
        }
    }
}

struct DemeSKParticles_Previews: PreviewProvider {
    static var previews: some View {
        DemoSceneKitParticles()
    }
}

关于ios - 如何在 SwiftUI 中使用 "*.scnp"文件进行按钮单击(iOS)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62046891/

相关文章:

iphone - 我在哪里可以找到并更改指定 iOS 应用程序名称的设置?

单击 map 注释时的 SwiftUI 操作

scenekit - 场景套件覆盖SCNNode渲染

ios - 我想在 Swift 中使用 Objective-C 的函数

ios - dyld:库未加载:AdjustSdk.framework

iphone - iOS : Call a method just one time

swift - 将过滤后的@Bindable 对象传递给 SwiftUI 中的多个 View

ios - 即使在指定 contentShape 后,ContextMenu 使用不正确的 cornerRadius

objective-c - 在 SceneKit 下可靠地访问和修改捕获的相机帧

swift - 3D 对象的重复模式(栅栏)