[英]Unable to properly size SKScene when working with SwiftUI
I am attempting to use SpriteKit
with a SwiftUI
based interface, but have encountered an issue when initializing my SKScene
.我正在尝试将SpriteKit
与基于SwiftUI
的接口一起使用,但在初始化我的SKScene
时遇到了问题。
First, my UIViewRepresentable
that contains the SKView
has been taken from a similar question :首先,包含UIViewRepresentable
的SKView
取自类似问题:
struct SpriteKitContainer: UIViewRepresentable {
let scene: SKScene
func makeUIView(context: Context) -> SKView {
return SKView(frame: .zero)
}
func updateUIView(_ view: SKView, context: Context) {
view.presentScene(scene)
}
}
A key piece here is that it requires the SKScene
to be initialized prior to SpriteKitContainer
being initialized.这里的一个关键部分是它需要在初始化SKScene
之前初始化SpriteKitContainer
。
I currently have the following abbreviated snippet doing this:我目前有以下缩写片段:
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)
}
}
I only include the TapGesture
to show why the body
is structured the way it is.我只包括TapGesture
来说明为什么body
是这样构造的。 With the code included, everything will work as expected, but the size used for the scene is obviously wrong (it fails to account for the padding, and navigation elements).包含代码后,一切都会按预期工作,但用于场景的大小显然是错误的(它无法考虑填充和导航元素)。
However, I have not found any other way to obtain a size or frame at this point, and sending over a .zero
size for the Scene(size:)
call will not size it correctly either.但是,此时我还没有找到任何其他方法来获取大小或帧,并且为Scene(size:)
调用发送.zero
大小也不会正确调整大小。
My assumption is that I am missing some precursor step as I am still ramping up with SwiftUI.我的假设是我缺少一些前导步骤,因为我仍在使用 SwiftUI。 Otherwise, I could calculate a new CGSize
given what I know, but that strikes me as the wrong approach here.否则,我可以根据我所知道的计算一个新的CGSize
,但这让我觉得这里的方法是错误的。
In SwiftUI you need to use GeometryReader as a proxy to get the view's current size (this happens every time the view is rebuilt).在 SwiftUI 中,您需要使用GeometryReader作为代理来获取视图的当前大小(每次重建视图时都会发生这种情况)。 You then want to resize your UIViewRepresentable based on the size of its parent only if the size has actually changed .然后,您需要根据其父级的大小调整您的 UIViewRepresentable 的大小,前提是该大小已实际更改。 I have a GeometryReader example here: https://github.com/joshuajhomann/SwiftUI-Spirograph我在这里有一个 GeometryReader 示例: https://github.com/joshuajhomann/SwiftUI-Spirograph
SKScene
has a didChangeSize
method for scenarios like that: SKScene
有一个didChangeSize
方法用于这样的场景:
override func didChangeSize(_ oldSize: CGSize) {
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
}
From Apples Documentation :从苹果文档:
This method is intended to be overridden in a subclass.此方法旨在在子类中被覆盖。 Typically, you use this method to adjust the positions of nodes in the scene.通常,您使用此方法来调整场景中节点的位置。
You don't need GeometryReader.您不需要 GeometryReader。 Just let SwiftUI itself give the available space to your SpriteView.只需让 SwiftUI 本身为您的 SpriteView 提供可用空间。 An important thing is, that the views size is not automatically the scene size.重要的是,视图大小不会自动成为场景大小。 So, you have to explicitly set the scene size.因此,您必须明确设置场景大小。
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
// ...
}
}
The scene size can be completely different from the view size , that's when the scene scaleMode comes into action.场景大小可以与视图大小完全不同,这就是场景 scaleMode 起作用的时候。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.