SKScene在iOS模拟器旋转后尺寸异常问题求助
问题分析与解决方案
1. 场景名称显示(null)的原因
SKScene的name属性不会自动从.sks文件名继承,默认值为nil,所以控制台打印时会显示'(null)'。解决方法有两种:
- 在
.sks文件的属性检查器中手动设置Name字段,对应你的场景文件名(比如CreditsScene); - 代码加载场景后手动赋值:
if let scene = SKScene(fileNamed: theScene) { scene.name = theScene // 其他设置... }
2. 旋转后尺寸异常的核心问题
你的代码存在两个关键错误:
didRotate中修改的是新场景而非当前显示的场景:你在didRotate里通过fileNamed新建了一个场景并修改尺寸,但这个场景从未被显示,最后调用showScene又重新加载了全新的场景,导致之前的尺寸修改完全无效;showScene每次新建SKView:每次调用showScene都执行view = SKView(),丢弃了之前的视图和场景,且没有根据当前旋转后的视图尺寸初始化场景。
3. 控制台before输出的含义
你打印的是通过fileNamed新建场景的初始尺寸——也就是你在.sks文件中预设的固定尺寸(比如竖屏的750x1334)。修改尺寸后的after输出是你手动设置的屏幕尺寸,但这个场景从未被呈现,所以对显示没有影响。
修复后的完整代码
class GameViewController: UIViewController { // 假设thisScene已提前初始化 var thisScene: String? override func viewDidLoad() { super.viewDidLoad() // 只初始化一次SKView,避免重复创建 let skView = SKView() skView.ignoresSiblingOrder = true skView.showsFPS = true skView.showsNodeCount = true view = skView } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) guard let sceneName = thisScene else { return } showScene(theScene: sceneName) } func showScene(theScene: String) { guard let skView = view as? SKView else { return } if let scene = SKScene(fileNamed: theScene) { scene.name = theScene // 使用SKView的bounds尺寸,适配旋转后的视图 scene.size = skView.bounds.size scene.scaleMode = .aspectFill skView.presentScene(scene) } } override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) { guard let skView = view as? SKView, let currentScene = skView.scene else { // 如果当前无场景,重新加载 guard let sceneName = thisScene else { return } showScene(theScene: sceneName) return } // 更新当前显示场景的尺寸为视图的最新尺寸 currentScene.size = skView.bounds.size } }
额外说明
- 使用
skView.bounds.size而非UIScreen.main.bounds:SKView的尺寸会跟随ViewController的视图自动适配旋转后的屏幕,比直接取屏幕尺寸更准确(尤其是考虑安全区、导航栏等情况); - 复用SKView:避免每次切换场景都重建视图,提升性能并保持视图状态的一致性。
内容的提问来源于stack exchange,提问作者user20439709
相关产品推荐
相关产品推荐

