简体   繁体   English

SwiftUI - 如何添加 Scenekit 场景

[英]SwiftUI - how to add a Scenekit Scene

How can I add a Scenekit Scene to a SwiftUI view?如何将 Scenekit 场景添加到 SwiftUI 视图?

I tried the following Hello World, using the standard Ship Scene example...我尝试了以下 Hello World,使用标准 Ship Scene 示例...

import SwiftUI
import SceneKit


struct SwiftUIView : View {
    var body: some View {

       ship()

        Text("hello World")


    }

But it didn't work:但它没有用: 在此处输入图片说明

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) Rawbee的回答做的工作,如果你正在创建一个SwiftUIView一个游戏项目中(默认的游戏项目,该项目的Xcode会为你创建)

But if you are in a Single View App project, you can create the same SceneView like this:但是如果你在一个Single View App项目中,你可以像这样创建相同的 SceneView:

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.art.scnassets文件夹(其中包含 2 个文件: ship.scntexture.png )从您的游戏项目ship.scn您的Single View App项目中。

Second第二

In your Single View App project create a new SwiftUI file — I called it: ScenekitView .在你的Single View App项目中创建一个新的 SwiftUI 文件——我称之为: ScenekitView This is a structure which conforms to the UIViewRepresentable protocol这是一个符合UIViewRepresentable协议的结构

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)我不是专业人士,但此代码对我有用(Xcode 11 beta 4)

In order for this to work, your SwiftUI View must conform to UIViewRepresentable .为了使其工作,您的 SwiftUI 视图必须符合UIViewRepresentable There's more info about that in Apple's tutorial: Interfacing with UIKit . 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

Note that you'll have to turn on live preview to see it working.请注意,您必须打开实时预览才能看到它的工作原理。

SceneKit + SwiftUI 预览

You don't need use UIViewRepresentable anymore.您不再需要使用UIViewRepresentable了。 Here's an update code for SwiftUI这是 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()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM