SwiftUI-如何添加Scenekit场景

Man*_*ero 2 scenekit swiftui xcode11

如何将Scenekit场景添加到SwiftUI视图?

我使用标准的Ship Scene示例尝试了以下Hello World ...

import SwiftUI
import SceneKit


struct SwiftUIView : View {
    var body: some View {

       ship()

        Text("hello World")


    }

Run Code Online (Sandbox Code Playgroud)

但这没有用: 在此处输入图片说明

raw*_*bee 9

为了使其工作,您的 SwiftUI 视图必须符合UIViewRepresentable. Apple 的教程中提供了更多相关信息:Interfaceting 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
Run Code Online (Sandbox Code Playgroud)

请注意,您必须打开实时预览才能看到它的工作原理。

SceneKit + SwiftUI 预览


Meh*_*hdi 6

如果您SwiftUIViewGame项目(Xcode将为您创建的默认游戏项目)中创建一个内部项目,Rawbee的答案就可以完成工作。

但是,如果您在Single View App项目中,则可以创建相同的SceneView,如下所示:

第一

art.scnassets文件夹(包含2个文件:ship.scntexture.png)从游戏项目中拖到Single View App项目中。

第二

在您的Single View App项目中,创建一个新的SwiftUI文件-我称它为:ScenekitView。这是符合UIViewRepresentable协议的结构

第三

将下面的代码复制并粘贴到此文件中,然后打开实时预览模式

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

Run Code Online (Sandbox Code Playgroud)

我不是专业人士,但是这段代码对我有用(Xcode 11 beta 4)


sko*_*nos 6

你不再需要使用UIViewRepresentable了。这是 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好的,但是你如何以这种方式过渡到另一个场景呢?SceneView 似乎没有必要的钩子。 (2认同)