【问题标题】:SwiftUI - how to add a Scenekit SceneSwiftUI - 如何添加 Scenekit 场景
【发布时间】:2019-11-06 16:23:20
【问题描述】:

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

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

import SwiftUI
import SceneKit


struct SwiftUIView : View {
    var body: some View {

       ship()

        Text("hello World")


    }

但它不起作用:

【问题讨论】:

    标签: scenekit swiftui xcode11


    【解决方案1】:

    为了使其正常工作,您的 SwiftUI 视图必须符合 UIViewRepresentable。在 Apple 的教程中有更多相关信息: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
    

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

    【讨论】:

      【解决方案2】:

      如果您在 Game 项目(Xcode 将为您创建的默认游戏项目)中创建 SwiftUIView,Rawbee 的答案就可以完成这项工作

      但如果您在 Single View App 项目中,您可以像这样创建相同的 SceneView:

      首先

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

      第二

      在您的 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
      
      

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

      【讨论】:

      • scn(xCode 调试器)已经过时了
      【解决方案3】:

      您不再需要使用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()
          }
      }
      

      【讨论】:

      • 好的,但是你会如何过渡到另一个场景呢? SceneView 似乎没有必要的钩子。
      猜你喜欢
      • 2020-03-31
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 2016-08-02
      • 2019-03-20
      • 1970-01-01
      • 2015-01-04
      • 2020-08-25
      相关资源
      最近更新 更多