ios - 使用按钮执行 SCNAction (SwiftUI)

标签 ios swiftui scenekit scnaction

使用 UIKit,我创建了一个带有对象的 SceneView,该对象可以在按下按钮时执行 SCNActions:

import UIKit
import SceneKit

class ViewController: UIViewController {


    @IBOutlet weak var ScenekitView: SCNView!
    
    
    var scene:SCNScene!
    var ship:SCNNode!
    
    
    @IBAction func button(_ sender: Any) {
        let sequence = SCNAction.sequence([SCNAction.moveBy(x: 0, y: 0, z: -10, duration: 0.5),SCNAction.moveBy(x: 0, y: 0, z: 10, duration: 0.5)])
        ship.runAction(sequence)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        scene = SCNScene(named: "mainScene.scn")!
        
        var cameraNode: SCNNode!
        cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
        cameraNode.scale = SCNVector3(1, 1, 0.5)
        cameraNode.eulerAngles = SCNVector3(0, 0, 0)

        ScenekitView.scene = scene
        
        ship = scene.rootNode.childNode(withName: "ship reference", recursively: true)!
        let pos = SCNVector3Make(0, 0, 0)
        
        ship.runAction(SCNAction.move(to: pos, duration: 1))
    }
}

现在我想使用 SwiftUI 实现同样的目标。

虽然在这个例子中,我可以让相机在 View 加载后执行一个操作,但我不知道如何让它在按下按钮后执行另一个操作。 特别是因为该节点是在另一个 subview 的函数中定义的。

这是我到目前为止得到的:

import SwiftUI
import SceneKit


struct ContentView: View { 
    var body: some View{

        VStack {
            ScenekitView().ignoresSafeArea()

            Button("move") {
               //here I would like to call a function including a SCNAction

            }
        }   
    }
}


struct ScenekitView : UIViewRepresentable {

    func makeUIView(context: Context) -> SCNView {

        let scene = SCNScene(named: "SceneFile.scn")!

        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
        scene.rootNode.addChildNode(cameraNode)
        
        cameraNode.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 5, duration: 1)))

        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene
        scnView.allowsCameraControl = false
    }
}

感谢您提供任何有用的想法。

最佳答案

您可以创建一个由父 View (ContentView) 拥有的对象,该对象将场景引用分发到 ScenekitView 并允许从 Button 进行访问>.

您可能想要调整细节(例如完成相机设置的位置),但这是一般概念:

class SceneManager : ObservableObject {
    let scene = SCNScene(named: "SceneFile.scn")!
    var ship:SCNNode
    
    init() {
        ship = scene.rootNode.childNode(withName: "ship reference", recursively: true)!
    }
    
    func move() {
        let pos = SCNVector3Make(0, 0, 0)
        ship.runAction(SCNAction.move(to: pos, duration: 1))
    }
}

struct ContentView: View {
    @StateObject var sceneManager = SceneManager()
    
    var body: some View{

        VStack {
            ScenekitView(scene: sceneManager.scene)
                .ignoresSafeArea()

            Button("move") {
                sceneManager.move()
            }
        }
    }
}


struct ScenekitView : UIViewRepresentable {
    var scene : SCNScene
    
    func makeUIView(context: Context) -> SCNView {
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
        scene.rootNode.addChildNode(cameraNode)
        
        cameraNode.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 5, duration: 1)))
        let scnView = SCNView()
        scnView.scene = scene
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.allowsCameraControl = false
    }
}

关于ios - 使用按钮执行 SCNAction (SwiftUI),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70958776/

相关文章:

ios - 无法监视事件循环并等待应用程序空闲

swift - 在 SwiftUI View 中应用 ClipShape 时,背景颜色从安全区域消失

ios - 如何从 Material Inspector 设置 colorBufferWriteMask

swift - 如何在 SceneKit 中绘制箭头?

iphone - NSUserDefaults 中的 NSMutableArray

ios - 使用 editActions 和 PerformSegue 编辑 UITableView 行?

ios - Color 与 UIColor 支持的默认亮/暗模式颜色

swift - 在代码中复制通过场景套件编辑器创建的物理体

ios - 关于使用 Storyboard的标签栏

swift - 特定功能同时在所有 View 上运行。我怎样才能让它一个接一个地运行?