如何防止 SceneKit 中的 SpriteKit 覆盖拉伸?

Posted

技术标签:

【中文标题】如何防止 SceneKit 中的 SpriteKit 覆盖拉伸?【英文标题】:How to prevent SpriteKit overlay in SceneKit to stretch? 【发布时间】:2017-12-24 18:07:35 【问题描述】:

在 WWDC 2017 SceneKit 会议中,他们建议使用 overlaySKScene 将 SpriteKit 层覆盖在 SceneKit 上用于 HUD 等。在我旋转 iPhone/iPad 之前它似乎工作正常。现在 SpriteKit 中的文本都被拉伸(如果从纵向变为横向)或缩小(如果从横向变为纵向)。无论如何,无论方向如何,都可以使文本或图形保持相同的大小?

    sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)

我以非常简单的方式解决了这个问题。只需调整 overlaySKScene 的大小并将所有内容重新定位在

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
    let width = sceneView.frame.height
    let height = sceneView.frame.width

    sceneView.overlaySKScene?.size = CGSize(width:width, height:height)
    ...

希望这可以帮助其他面临类似问题的人。

【问题讨论】:

【参考方案1】:

你需要看看 SKScene 是如何工作的:

这意味着将叠加层设置为给定方向的 iphone 屏幕大小: sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)

现在我假设没有其他任何变化,这意味着您的 scaleMode 设置为 .fill,这意味着拉伸图形直到所有边都被填充。

坐在纵向模式时,您不会注意到任何东西,因为它是 1:1 比例。

现在您将其翻转为横向。

系统将尝试将您的纵向屏幕尺寸转换为横向尺寸。

这意味着你会得到粗短的图形,因为它会拉伸你的两侧,并缩小你的顶部和底部以填充所有边缘。

这就是为什么编写像sceneView.overlaySKScene = SKScene(size: sceneView.frame.size) 这样的代码不好的原因。你最终会让自己感到困惑。

我总是建议使用 SKS 文件,或者设置恒定的场景大小,所以sceneView.overlaySKScene = SKScene(size: CGSize(750,1334))

然后,根据我想要显示叠加层的方式,我使用适当的缩放模式。

在我希望叠加层占据屏幕空间的确切百分比的游戏中,我使用.aspectFill

在我希望叠加层占用确切数量的像素空间的游戏中,我使用.resizeFill

通过查看scaleMode,我现在知道我的场景应该如何表现。

使用.aspectFill,我将需要检测方向何时翻转,届时要么呈现与方向对应的SKS,要么移动与方向对应的节点。

对于.resizeFill,我需要创建一个在方向翻转时遵守的调整大小方法,并根据新大小按比例移动节点。

您可以在ViewController 中检测方向何时翻转

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) 

然后使用视图进入场景以调用您的调整大小功能/加载新场景。

【讨论】:

以上是关于如何防止 SceneKit 中的 SpriteKit 覆盖拉伸?的主要内容,如果未能解决你的问题,请参考以下文章

SceneKit:如何将节点的移动限制在本地的一个轴上,而不是整个世界

如何从 SceneKit 中的 .dae 文件访问文本元素?

带有 SceneKit 的 SwiftUI:如何使用视图中的按钮操作来操作底层场景

如何将 .dae 文件加载到 iOS SceneKit 中的 SCNNode 中?

从 Scenekit 中的世界变换中提取旋转

如何在 SceneKit 中显示金属和透明纹理?