【问题标题】:Unable to properly size SKScene when working with SwiftUI使用 SwiftUI 时无法正确调整 SKScene 的大小
【发布时间】:2019-10-07 14:17:42
【问题描述】:

我正在尝试将SpriteKit 与基于SwiftUI 的接口一起使用,但在初始化我的SKScene 时遇到了问题。

首先,包含SKViewUIViewRepresentable 取自similar question

struct SpriteKitContainer: UIViewRepresentable {
    let scene: SKScene

    func makeUIView(context: Context) -> SKView {
        return SKView(frame: .zero)
    }
    
    func updateUIView(_ view: SKView, context: Context) {
        view.presentScene(scene)
    }
}

这里的一个关键部分是它需要在初始化 SpriteKitContainer 之前初始化 SKScene

我目前有以下缩写的 sn-p 这样做:

import SwiftUI
import SpriteKit

struct GameView: View {
    @State private var isEnabled = true
    
    var body: some View {
        let tapGesture = TapGesture()
            .onEnded { value in }
        
        // This size is obviously wrong
        let size = UIScreen.main.bounds.size
        let scene = Scene(size: size)
        scene.scaleMode = .resizeFill
        
        return SpriteKitContainer(scene: scene)
            .disabled(!isEnabled)
            .frame(maxWidth: .infinity,
                   maxHeight: .infinity,
                   alignment: .center)
            .gesture(tapGesture)
            .padding(.all, 30)
    }
}

我只包含TapGesture 来说明为什么body 的结构是这样的。包含代码后,一切都会按预期工作,但场景使用的大小显然是错误的(它无法考虑填充和导航元素)。

但是,我目前还没有找到任何其他方法来获取大小或框架,并且为 Scene(size:) 调用发送 .zero 大小也不会正确调整大小。

我的假设是,由于我仍在使用 SwiftUI,因此我错过了一些前导步骤。否则,我可以根据我所知道的计算出一个新的CGSize,但这让我觉得这里的方法是错误的。

【问题讨论】:

  • 你的场景总是会根据视图调整大小,如果你需要填充,你需要在视图级别考虑它

标签: ios swift sprite-kit swiftui ios13


【解决方案1】:

在 SwiftUI 中,您需要使用 GeometryReader 作为代理来获取视图的当前大小(每次重建视图时都会发生这种情况)。然后,您希望根据父级的大小调整 UIViewRepresentable 的大小只有在大小实际发生变化时。我在这里有一个 GeometryReader 示例:https://github.com/joshuajhomann/SwiftUI-Spirograph

【讨论】:

【解决方案2】:

SKScene 有一个 didChangeSize 方法用于这样的场景:

override func didChangeSize(_ oldSize: CGSize) {
    self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
}

来自Apples Documentation

此方法旨在在子类中被覆盖。通常,您 使用此方法调整场景中节点的位置。

【讨论】:

    【解决方案3】:

    您不需要 GeometryReader。只需让 SwiftUI 本身为您的 SpriteView 提供可用空间。重要的是,视图大小不是自动场景大小。因此,您必须明确设置场景大小。

    import SwiftUI
    import SpriteKit
    
    struct ContentView: View {
    
        var body: some View {
            SpriteView(scene: spriteKitScene)
        }
    
        private var spriteKitScene : SKScene {
            let scene = SpriteKit_View()
            scene.scaleMode = .aspectFit
            return scene
        }
    
    }
    
    class SpriteKit_View : SKScene {
    
        override func didMove(to view: SKView) {
    
           // Set the scene size as you want, in my case 
              equal to the views size
    
           size = view.frame.size
           // ...
        }
    }
    

    场景大小可以与视图大小完全不同,这就是场景 scaleMode 发挥作用的时候。

    【讨论】:

      猜你喜欢
      • 2012-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 2011-03-24
      相关资源
      最近更新 更多