You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:01:14