我正在通过 Adobe AIR (3.1) 将基于 Flash Player 的游戏移植到桌面(OSX 和 Windows)。移植到 AIR 本身进行得相当顺利。我遇到的一个问题是游戏将通过 Steam 网络分发。为了与 Steam 客户端交互,我不得不编写一个原生扩展来将 Steam SDK API 暴露给 AS3。两个平台都实现了本机扩展支持,我可以根据需要启动应用程序并与 Steam 通信。
我遇到麻烦的领域是处理 Steam 的叠加层,它在激活时会渲染游戏的顶部。本质上,当游戏启动时,Steam 客户端会暂停该进程,以便将其 Overlay 库与 D3D 或 OpenGL 挂钩。最初,由于 AIR 应用程序描述符的默认渲染模式设置为“auto”,因此 Overlay 根本没有出现。但是,一旦我将渲染模式切换为“gpu”,叠加层就会根据需要出现。
在 OSX 方面,一切都按预期工作。我可以很好地切换进出叠加层。在光谱的窗口端,当我激活覆盖时我遇到了一些问题。具体来说,当启用 Overlay(它在游戏上方渲染)并且我移动鼠标或生成键盘输入时,Overlay 和游戏都“冻结”(渲染停止)2-3 秒。另外,我注意到当我在游戏运行的情况下打开任务管理器时,cpu 使用率大约是 75-80%。当我第一次激活 Overlay(这是所需的)时,cpu 使用率保持不变。但是,当我移动鼠标光标或按下键盘上的某个键时,cpu 使用率下降到大约 1%。我们测试过的 5 台 Windows 机器(2 台 XP,3 台 Win 7)中的 4 台出现了这个问题。自然,我首先就这个问题联系了 Valve,因为这仅在启用 Overlay 时发生。我已经上传了 OSX 和 Windows 版本供他们的开发人员调试;但是,我的联系人建议我也了解有关 AIR 渲染/输入的更多信息。
以下是 Steam 开发人员的帖子片段,详细说明了叠加层的工作原理:
“在 Windows 上覆盖的要求如下:
- 游戏必须使用 D3D7、D3D8、D3D9、D3D10、D3D11 或 OpenGL
- 游戏必须定期快速调用 D3D Present() 或 OpenGL SwapBuffers()(这些调用被覆盖层钩住,并为其提供工作机会)。例如,仅在鼠标移动或屏幕上的图形实际发生变化而不是每一帧时才调用这些函数的 2D 游戏将无法正常运行。
- 游戏应使用标准 Win32 输入消息、原始 Win32 输入消息或 DirectInput 进行输入,然后覆盖层将检测热键并在活动时隐藏/阻止游戏中的输入事件。
听起来您的游戏可能违反了 #2 并且有时会在覆盖处于活动状态时停止调用 Present/SwapBuffers。如果您调用这些函数来响应用户输入,则可能会发生这种情况,而用户输入现在由于覆盖被激活而被阻止。即使没有发生输入事件,您也应该保证保持定期抽帧和交换。”
经过一番刺激,Valve 开发人员分析了我的应用程序,以确定 Game Overlay 是否存在任何特定问题。不幸的是,他们无法在 Overlay 本身中发现任何事情。这几乎意味着 Windows 上的 AIR 不喜欢 Overlay 阻止 Win32 输入消息。以下是 Valve 开发人员的回复:
“我得到了你的 depot 并进行了一些测试。覆盖中没有发生异常情况。在问题发生时使用 xpref 分析你的应用程序并采取一些小型转储来检查调用堆栈,看起来应用程序只是完全阻塞并且在此期间使用零 CPU被阻塞,当它发生时它仅以大约 1 秒的间隔调用 Present() 直到它恢复(可能在 AIR 代码的某处有 1 秒的超时).很难获得很多细节,因为我没有任何符号AIR 运行时库。
然而,这看起来确实与输入状态和 AIR 对 win32 输入消息停止不满意有关。如果我将覆盖更改为在激活后根本不阻止任何输入(这显然在可用性方面存在一些相当大的问题,但只是出于测试目的。)那么问题就不会发生。AIR 代码可能有一些奇怪的逻辑,如果它看到一些特定的 WM_WHATVER 消息,它会在之后期待另一个消息并阻止它以某种方式等待。
希望您能在您身边或与 Adobe 一起研究为什么应用程序在这些情况下表现不佳并开始阻塞并且不定期显示。”
我在 Adobe 论坛上发过帖子,但那里没有这样的运气。主要是,我希望有人以前处理过这个问题,或者对我如何解决这个问题有所了解。任何建议、意见或想法将不胜感激!