在SwiftUI中使用SpriteKit

Geo*_*e_E 6 ios sprite-kit skscene swift swiftui

在中创建SpriteKit场景时出现问题SwiftUI。我最初将这个项目创建为一个SwiftUI项目。

这是我到目前为止的代码:

ContentView.swift:

/// Where the UI content from SwiftUI originates from.
struct ContentView : View {
    var body: some View {
        // Scene
        SceneView().edgesIgnoringSafeArea(.all)
    }
}
Run Code Online (Sandbox Code Playgroud)

SceneView.swift:

/// Creates an SKView to contain the GameScene. This conforms to UIViewRepresentable, and so can be used within SwiftUI.
final class SceneView : SKView, UIViewRepresentable {

    // Conformance to UIViewRepresentable
    func makeUIView(context: Context) -> SKView {
        print("Make UIView")
        return SceneView(frame: UIScreen.main.bounds)
    }
    func updateUIView(_ uiView: SKView, context: Context) {
        print("Update UIView")
    }

    // Creating scene
    override init(frame: CGRect) {
        super.init(frame: frame)

        let scene = Scene(size: UIScreen.main.bounds.size)
        presentScene(scene)
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Run Code Online (Sandbox Code Playgroud)

Scene.swift:

/// The scene for the game in SpriteKit.
final class Scene : SKScene {

    override func didMove(to view: SKView) {
        super.didMove(to: view)

        print("Scene didMove:")
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

问题是场景正在重新加载多次,如日志所示(因为print代码中有s):

场景didMove:

制作UIView

场景didMove:

更新UIView


如您所见,Scene didMove:被打印两次。我只想调用一次,因为我想在这里创建我的精灵。有任何想法吗?

paw*_*222 8

SwiftUI 2

现在有一个本地视图负责显示SKScene- 它被称为SpriteView.

假设我们有一个简单的SKScene

class Scene: SKScene {
    override func didMove(to view: SKView) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用 aSpriteView直接在 SwiftUI 视图中显示它:

struct ContentView: View {
    var scene: SKScene {
        let scene = Scene()
        scene.size = CGSize(width: 300, height: 400)
        scene.scaleMode = .fill
        return scene
    }

    var body: some View {
        SpriteView(scene: scene)
            .frame(width: 300, height: 400)
            .edgesIgnoringSafeArea(.all)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到更多信息:


Mat*_*ini 7

您的SceneView实现不正确。

SwiftUI使用结构在其DSL中构建视图-而不是视图。

您要创建一个struct符合的UIViewRepresentable

struct SceneView: UIViewRepresentable {

    let scene: SKScene

    func makeUIView(context: Context) -> SKView {
        // Let SwiftUI handle the sizing
        return SKView(frame: .zero)
    }

    func updateUIView(_ uiView: SKView, context: Context) {
        uiView.presentScene(scene)
    }
}
Run Code Online (Sandbox Code Playgroud)

有关如何将UIKit基于视图的视图移植到SwiftUI的更多信息,请参见以下出色的WWDC 2019视频:集成SwiftUI