SwiftUI - how to add a Scenekit Scene

前端 未结 3 533
萌比男神i
萌比男神i 2021-02-04 19:57

How can I add a Scenekit Scene to a SwiftUI view?

I tried the following Hello World, using the standard Ship Scene example...

import SwiftUI
import Scene         


        
相关标签:
3条回答
  • 2021-02-04 20:30

    You don't need use UIViewRepresentable anymore. Here's an update code for SwiftUI

    import SwiftUI
    import SceneKit
    
    struct ContentView: View {
        var scene: SCNScene? {
            SCNScene(named: "Models.scnassets/Avatar.scn")
        }
    
        var cameraNode: SCNNode? {
            let cameraNode = SCNNode()
            cameraNode.camera = SCNCamera()
            cameraNode.position = SCNVector3(x: 0, y: 0, z: 2)
            return cameraNode
        }
    
        var body: some View {
            SceneView(
                scene: scene,
                pointOfView: cameraNode,
                options: [
                    .allowsCameraControl,
                    .autoenablesDefaultLighting,
                    .temporalAntialiasingEnabled
                ]
            )
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    0 讨论(0)
  • 2021-02-04 20:35

    Rawbee's answer does the job if you are creating a SwiftUIView inside a Game project (the default game project that Xcode will create for you)

    But if you are in a Single View App project, you can create the same SceneView like this:

    First

    drag the art.scnassets folder (which contains 2 files: ship.scn and texture.png) from your game project to your Single View App project.

    Second

    In your Single View App project create a new SwiftUI file — I called it: ScenekitView. This is a structure which conforms to the UIViewRepresentable protocol

    Third

    Copy and paste the code below to this file and turn on live preview mode

    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
    
    

    I'm not a pro but this code worked for me (Xcode 11 beta 4)

    0 讨论(0)
  • 2021-02-04 20:46

    In order for this to work, your SwiftUI View must conform to UIViewRepresentable. There's more info about that in Apple's tutorial: Interfacing with UIKit.

        import SwiftUI
    
    struct SwiftUIView : UIViewRepresentable {
    
        func makeUIView(context: Context) -> UIView {
            return UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController()!.view
        }
    
        func updateUIView(_ view: UIView, context: Context) {
    
        }
    }
    
    #if DEBUG
    struct SwiftUIView_Previews : PreviewProvider {
        static var previews: some View {
            SwiftUIView()
        }
    }
    #endif
    

    Note that you'll have to turn on live preview to see it working.

    0 讨论(0)
提交回复
热议问题