如何同时使用 SwiftUI 和 SceneKit?

Posted

技术标签:

【中文标题】如何同时使用 SwiftUI 和 SceneKit?【英文标题】:How to use SwiftUI and SceneKit together? 【发布时间】:2020-04-13 16:28:31 【问题描述】:

我在 SwiftUI 的框架内的场景中显示了一个 SCNCylinder。我想将它围绕某个轴旋转 180º。在 SwiftUI 视图中按下180º(某种)按钮后,我希望圆柱体旋转。目前我可以旋转一次,但第二次按下按钮时它不会旋转。我尝试先将旋转角度定义为零,然后再定义为 180º,但在这样做之后,整个事情在我按下按钮后就崩溃了。我只想在按下按钮后第二次旋转圆柱体。

这是我的代码:

//SwiftUI view

struct ContentView: View 
@State var rotationAngle: Angle = .degrees(0)
var body: some View 

    VStack

        Text("180º").onTapGesture 
           self.rotationAngle = .zero
           self.rotationAngle = .degrees(180)

        

        
        SceneKitView(radius: 0.02, height: 2, angle: $rotationAngle)
            .position(x: 200.0, y: 140)
            .frame(width: 300, height: 300, alignment: .center)
        

     

  

//SceneKit View

 struct SceneKitView: UIViewRepresentable 

  @Binding var angle: Angle

 let cylindernode: SCNNode

 init(radius: CGFloat, height: CGFloat, angle: Binding<Angle>) 

    let cylinder = SCNCylinder(radius: radius, height: height)
    cylinder.firstMaterial?.diffuse.contents = UIColor.green
    self.cylindernode = SCNNode(geometry: cylinder)
    self.cylindernode.position = SCNVector3(0, 0, 0)
    self.cylindernode.orientation = SCNVector4(0, 0, 0, 0)
    cylindernode.pivot = SCNMatrix4MakeTranslation(0, -1, 0)

    self._angle = angle



//SCNScene

func makeUIView(context: UIViewRepresentableContext<SceneKitView>) -> SCNView 

    let sceneView = SCNView()
    sceneView.scene = SCNScene()
    sceneView.autoenablesDefaultLighting = true
    sceneView.allowsCameraControl = true
    sceneView.scene?.rootNode.addChildNode(cylindernode)
    return sceneView


func updateUIView(_ sceneView: SCNView, context: UIViewRepresentableContext<SceneKitView>) 

 //Rotation animation

    let rotation = CABasicAnimation(keyPath: "transform.rotation")
    rotation.isRemovedOnCompletion = false
    rotation.duration = 5
    cylindernode.addAnimation(rotation, forKey: "rotation")
    cylindernode.rotation = SCNVector4(1, 0, 0, angle.radians)






删除self.rotationAngle = .zero 行后,代码运行良好,但视图没有更新。但是,如果我保留这条线,那么在我按下按钮后,整个事情就会崩溃。

【问题讨论】:

如果你把它设置为 180,那就是它要旋转到的地方。尝试增加你的角度(可能会增加一点),这样你就可以看到它在移动......或使用 Rotate(By: ...) 【参考方案1】:

试试这个:但是因为你问的问题很多而且它们都很基础,也许你应该检查一些初学者的快速课程来学习如何设置变量......这与 Scenekit 和 SwiftUI 无关 -它只是改变一个变量。

struct ContentView: View 
    @State var rotationAngle: Angle = .degrees(0)
    var body: some View 

        VStack

            Text("180º").onTapGesture 
                self.rotationAngle += .degrees(90)
                print(self.rotationAngle)
            
            SceneKitView(radius: 0.02, height: 2, angle: $rotationAngle)
                .position(x: 200.0, y: 140)
                .frame(width: 300, height: 300, alignment: .center)
        
    

【讨论】:

以上是关于如何同时使用 SwiftUI 和 SceneKit?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI – 将数据从 SwiftUIView 传递到 SceneKit

如何使用 SwiftUI 更新不同的视图?

在 SceneKit 中,如何在不同大小的对象上平铺纹理,同时保持最小的绘制调用?

有啥方法可以将视图从 swiftUI 更改为 UIKit?

如何让用户在 SwiftUI 文本字段中仅使用数字输入货币,同时保留 $ 和 .?

将scenekit和spritekit组合在一个屏幕中