好的,经过数周的研究,我已经找到了一些解决这个问题的方法。在开始之前,让我先解释一下我的设置。我正在使用一个Storyboard中的NSViewController来容纳SKView。我已经在MacBook Pro (Retina, 15-inch, Early 2013)上测试了这个解决方法,但我不知道我以下呈现的解决方法是否适用于其他Mac。我相信应该是可以的,等有机会时我会测试并查看以下解决方法是否可行。
因此,在开始之前,让我们回顾一下问题所在。问题在于通过点击全屏按钮使您的应用程序进入全屏模式会导致FPS大幅下降。以下是如何启用全屏按钮:
self.view.window!.collectionBehavior = .FullScreenPrimary
然后我搜索了一下,并找到了另一种使用以下代码进入全屏的方法:
self.view.enterFullScreenMode(NSScreen.mainScreen()!, withOptions: nil)
但是我的FPS仍然大幅下降。请记住,在最大化窗口模式或即使菜单栏可见的全屏模式下,我没有FPS问题!(请参见问题中的图片)。
于是我尝试了一种不太高级的全屏模式方法。我在苹果公司的指南中找到了一份指南here
使用指南中的一些代码,我将窗口大小设置为显示器的大小,并将窗口定位在所有OS X UI上方,以进入全屏模式。其代码如下:
self.view.window!.styleMask = NSBorderlessWindowMask
self.view.window!.level = Int(CGWindowLevelForKey(Int32(kCGMainMenuWindowLevelKey))) + 1
self.view.window!.opaque = true
self.view.window!.hidesOnDeactivate = true
let size = NSScreen.mainScreen()!.frame.size
self.view.window!.setFrame(CGRect(x: 0, y: 0, width: size.width, height: size.height), display:true)
但是,遗憾的是,出现了同样的问题... FPS 就像之前一样下降了。
所以我想,如果我改变窗口的大小/位置会怎么样。于是我试着将窗口向下移动,只留下菜单栏如下所示。这个方法奏效了。FPS 不再下降了。但显然它并不是真正的全屏,因为菜单栏仍然可见。
self.view.window!.setFrame(CGRect(x: 0, y: 0, width: size.width, height: size.height-NSApplication.sharedApplication().mainMenu!.menuBarHeight), display:true)
事实上,只需将窗口大小调整1个点,即可解决fps下降的问题。因此,这个bug必须与苹果在窗口大小与屏幕大小匹配时进行的优化(多么讽刺)有关。
不相信吗?以下是链接中的一句话:
“OS X v10.6及更高版本会自动优化屏幕大小的窗口性能。”
因此,要解决这个问题,我们只需要将窗口的高度增加1个点,这样就可以防止OS X尝试优化我们的窗口。这会导致您的应用程序在顶部略微被剪裁,但1个像素根本不会引起注意。在最坏的情况下,您可以将您的节点位置调整1个点来解决这个问题。
为了方便起见,以下列出了两种解决方法。这两种解决方法都不会导致FPS下降。您的应用程序应该与在最大化窗口模式下的运行方式相同。第一种解决方法将您的应用程序置于全屏状态,并在顶部显示菜单栏。第二种解决方法将您的应用程序置于完全全屏模式,没有菜单栏。
self.view.window!.styleMask = NSBorderlessWindowMask
self.view.window!.level = Int(CGWindowLevelForKey(Int32(kCGMainMenuWindowLevelKey))) + 1
self.view.window!.opaque = true
self.view.window!.hidesOnDeactivate = true
let size = NSScreen.mainScreen()!.frame.size
self.view.window!.setFrame(CGRect(x: 0, y: 0, width: size.width, height: size.height-NSApplication.sharedApplication().mainMenu!.menuBarHeight), display:true)
解决方法2:全屏无菜单栏
self.view.window!.styleMask = NSBorderlessWindowMask
self.view.window!.level = Int(CGWindowLevelForKey(Int32(kCGMainMenuWindowLevelKey))) + 1
self.view.window!.opaque = true
self.view.window!.hidesOnDeactivate = true
let size = NSScreen.mainScreen()!.frame.size
NSMenu.setMenuBarVisible(false)
self.view.window!.setFrame(CGRect(x: 0, y: 0, width: size.width, height: size.height+1), display:true)
如果由于某种原因这些解决方法不起作用,尝试调整窗口的大小/位置。此外,根据您是否有其他视图(例如对话框)不应重叠到应用程序上,请更改窗口级别。
还请记得向苹果提交错误报告。
关于NSBorderlessWindowMask的附加信息
这些解决方法使用了一个NSBorderlessWindowMask。这种类型的窗口在键盘窗口发生变化时不接受键盘输入。因此,如果您的游戏使用键盘输入,您需要覆盖以下内容。请参见
这里。
class CustomWindow: NSWindow {
override var canBecomeKeyWindow: Bool {
get {
return true
}
}
override var canBecomeMainWindow: Bool {
get {
return true
}
}
}
更新:一些不好的消息
我在 MacBook Air 上尝试了这个解决方法,但除非减少约100个点(这显然非常明显),否则它将无法正常工作。我不知道为什么。andyvn22的解决方案也是一样。我还注意到,很少情况下,可能是每60次启动中的一次,提供的解决方案根本无法在 MacBook Air 上正常工作。唯一的修复方式是重新启动应用程序。也许 Max Book Air 是一个特例。也许缺乏图形卡与这个问题有关。希望苹果能解决这个问题。现在,我在支持全屏和不支持全屏之间犹豫不决。我真的希望用户能够进入全屏模式,但同时我又不想冒着让用户失去一半FPS的风险。