首页大图
成功解决✅

排障–奥日2加载一下就闪退(已解决附补丁)

前情提要

前一阵子Steam上面奥日2打折,就买了一个,但是都玩不了。

具体故障很是神奇,打开游戏就在奥日奔跑的页面,有时候奔跑会剧烈掉帧,最后就出来个unity崩溃弹窗,整个游戏自动关闭。但是这一套不能稳定复现,有时候甚至能进去游戏,但是就算进去了也没有声音。

网上解决方法

首先肯定是查一下网上的类似问题的解决方法拉,我找到了这些:

1.切换时区。准确点说,是把系统里面呗吞掉的时区改成北京时间,就行。 记录一次解决奥日2无限加载问题的经历-百度贴吧
2.切换版本。Steam提供了老一点的版本的下载,直接切换就行。(也就是那个开发者补丁,或者叫做patch2版本)开发者补丁解决ori2开始游戏黑屏问题-百度贴吧
3.更新显卡驱动。A卡驱动,懂得都懂🤣
4.启用Steam输入,来避免手柄导致的闪退。 https://www.bilibili.com/video/BV1SvB5YfEDh
5.更新vc++ …我这么懂电脑不至于卡在这个,基本忽略了。 解决奥日2无限加载和加载完黑屏-百度贴吧
6.文件夹直接启动。 【精灵与萤火意志】为什么我每次登录游戏都会闪退? – 知乎
7.调整声卡的输出格式,关闭空间音频,改配置文件把音频设备设为默认,api设为默认。 steam的奥日精灵与萤火意志为什么没有声音? – 知乎
8.锁定cpu核心来启动,只允许游戏调用1-2个大核心,进去游戏了再改。
9.使用dxvk转译后运行。—-甚至换了显卡,拿intel核显和P4单独运行。

但是,对我来说,都没用….. 特别是patch2版本,我给予了最大希望的,也是一样的报错,加载还慢不少。

表情包 玖玖瑠what can i say

先来放个环境吧。我当时最开始的时候是Win 10 22H2 版本是1904x.2xxx的版本。

硬件一直不变,是这个

项目值
CPUIntel i9-13900HK(ES 工程样品),代号Q1HY
内存32 GB DDR5 6000 c38 美光颗粒
主显卡AMD Radeon RX 9070 XT,16 GB 显存(驱动 32.0.31041.1004)
副显卡NVIDIA Tesla P4,8 GB 显存
操作系统Windows 10 专业工作站版(64 位)
版本Build 19045(22H2),系统盘安装于 2026-06-18

其中这个CPU看起来是疑点重重,其实是啥毛病没有,当他是个13600k就行了,确认无bug。

那接下来,就是排障了

2026/6/15 –蓝色大肥鱼协助(失败)

6月–先是报错与分析

首先,报错肯定看log和系统日志。正好,unity游戏就有自己详细的报错。来看看吧

C:\Users\你的用户名\AppData\Local\Temp\Moon Studios\OriAndTheWilloftheWisps\Crashes
Crash!!!
: Wwise: Cannot create streaming I/O device. : 
UnityEngine.Logger:Log(LogType, Object, Object)
UnityEngine.Debug:LogError(Object, Object)
AkWwiseInitializationSettings:InitializeSoundEngine(AkWwiseInitializationSettings, WwiseBootstrapConfiguration)
Moon.Wwise.WwiseIntegration:Initialize(AkWwiseInitializationSettings, WwiseBootstrapConfiguration)
Moon.Wwise.WwiseBootstrap:Initialize()
Moon.Wwise.WwiseBootstrap:Awake()
UnityEngine.Object:Instantiate(T)
GameController:WarmUpResources()
GameController:Initialize()
StartupState:OnEnterState()
Bootstrap:Awake()
UnityEngine.Object:Instantiate(T)
Object:Instantiate(TObject)
GamePlaceholder:Awake()
 

emmm,看起来是wwise的streaming I/O device 炸了。这个一眼看是音频的Bug啊,直接从音频接口开始操刀(其实不是,被大肥鱼坑了,这个streaming似乎是从硬盘流式读取而非音频流式输出)

ds原话(呃呃坑死我了)
## 问题根因
Steam Streaming Speakers 虚拟扬声器干扰了 Wwise 2019.1.7 音频引擎的设备枚举。

- Wwise 遍历系统音频设备时,Steam 串流虚拟扬声器返回了无效参数
- 导致流式 I/O 设备创建失败
- Wwise 内部对象虚函数表损坏          ← 就是这里
- AK::StreamMgr::SetFileLocationResolver 调用时跳转到堆地址 → 访问违规

某个对象坏了 → 程序通过它做间接调用 → 跳到了不该跳的地方

因为之前也碰到过音频不兼容导致的说法,先把steam虚拟扬声器禁用了看看。欸,居然进去了????稳定进去了几次,基本没有闪退,(虽然没声音)这也为这一次排障的路线偏离打下了伏笔。正好ds给出的结论是dll与内存布局的问题,说是win和老游戏的什么内存布局产生的冲突。于是,第一次折腾开始了

然后是尝试修复

当时锁定了这个方向,我做出了如下的努力。

1.在虚拟机里面装上同样版本的系统,发现故障依旧。更新到最新的win10版本之后,能玩了,一切正常。对比一下差异,音频相关的dll确实有一定的改变。还有一个变量就是amd显卡驱动
2.按照ds的推荐,关掉了amd的掉驱动检测服务和xbox gamebar,来尝试改变内存布局(A黑头子ds)
3.更新最新系统,和Primo Cache老版本驱动搏斗了2天终于装上了(微软也改了磁盘方面的驱动导致冲突)
4.禁用steam虚拟扬声器和amd音频输出,只留下一个螃蟹声卡
5.在虚拟机里面用ai的小脚本抓差异
6.臭骂amd并且更新显卡驱动

不过 ,可惜,还是没用…

表情包 al信浓 哭

2+3让我的闪退少了一点,但是仍然不能稳定进去游戏,也不能出声音

6月复盘

现在复盘一下,ds这里面的错误可不少。
① 那个函数名是猜的

AK::StreamMgr::SetFileLocationResolver(文件位置解析器)—— 听起来很专业,但没有调试符号时,工具只能拿"离得最近的导出符号名"去标记地址。九月算 RVA 再反汇编,发现那里根本是虚函数间接调用,不是什么文件位置解析器。

② 不是”写入”,是”执行”

六月文本日志写的是 Write to location … caused an access violation(写入冲突)。九月看转储才发现 ExceptionInformation[0] = 8 = 执行违规。按照微软文档,**用户态数据执行保护(DEP)违规**——也就是”试图执行一段不允许执行的内存”

那么,这一点的改善是哪里来的?也许是内存布局变了带来的神奇小优化吧..禁用服务、关掉 Game Bar,改变的是谁往进程里塞 DLL、堆内存怎么复用 —— 说白了就是改变了撞车的概率。也正因为这样,这类操作永远只能”减轻”,不可能”治好”。概率降下来了,故障本身一动没动。

还好Steam客服给力,给我退款了。不过游戏文件我没删,要是哪天有救了呢?这可不是我玩盗版啊,是电脑不允许

2026/9/17 GPT6 Astra神仙救世

9月分析–抓真凶:错误码 87

最强llm出来了,手上有个pro20x和一堆reset,不猛猛蹬岂不浪费?正巧想到了这个bug,就让他们一较高下。

既然模型性能上来了,那要抓肯定要抓根本原因。就直接,来写一个补丁+详细冲突分析吧。
先是抓到了这么个东西:

Wwise: Cannot create streaming I/O device.
WwiseUnity: Failed to initialize the sound engine. Abort.

GPT的世界知识还是暴打ds,一眼看出这可不是什么音频输出的bug,这是音频组件读取音频文件的问题啊!
原始报告写的出错的是这个:

AK::StreamMgr::SetFileLocationResolver

但是,工具他只能拿到邻近的导出符号名去猜地址,并不知道详细信息。于是gpt开始了他的反编译:

AkSoundEngine.dll + 0x5B0C8
AkSoundEngine.dll + 0x5B16E

这是紧跟在虚函数间接调用之后,而崩溃时线程想跳转的目标地址,根本不在正常模块的代码区里。
除此之外,还有个冲突:Unity 的文本报告写的是”写入冲突(Write to location)”,但是ExceptionInformation[0]的值是8,表示用户态数据执行保护(DEP)违规。对不上啊。

接下来就是抓真正失败的调用了。


线程优先级:    0
线程核心掩码:  0xFFFFFFFC
线程栈大小:    128 KiB

SetThreadPriority      返回 1   → 成功
SetThreadAffinityMask  返回 0   → 失败
Windows 错误码          87      → ERROR_INVALID_PARAMETER
随后发生                0xC0000005 → 访问冲突

有了错误码,自然就有了假设,游戏请求的掩码是 `0xFFFFFFFC`,而机器进程报告可用的只有 `0xFFFFF`,是不是请求了不允许的高位?但是随后的尝试又把这个假设给否定了。
把掩码从 `0xFFFFFFFC` 截断到 `0xFFFFC`,仍然87报错。这么说,禁用核心还是有点用的,但是不多。

反汇编:失败之后发生了什么

那么接下来,只能上反汇编了!GPT虽然逆向甲很厚,但是在这种拯救可怜穷鬼玩家的时候可不会藏着掖着,直接开整。
接下来就是GPT show time了,直接黏贴吧😂我也搞不懂啊

既然定位不到"为什么失败",就换个问题问:**失败之后,程序做了什么?**

反汇编这段逻辑之后,看到了一个要命的顺序:

```cpp
thread = CreateThread(/* 创建后立即可运行 */);

if (!ConfigurePriorityAndAffinity(thread)) {   // 这里失败了(错误 87)
    CloseHandle(thread);
    thread = nullptr;                          // 句柄被清空
    return InitializationFailed;
}

// ……后续清理阶段
if (thread != nullptr) {                       // 句柄是空的,于是跳过等待
    WaitForSingleObject(thread, INFINITE);
}
// 然后,销毁线程还在用的那些对象
```

关键点在于:**关闭线程句柄 ≠ 结束线程。**

句柄可以理解成"访问系统对象的一张票"。把票撕了,线程还在跑。微软的 `CloseHandle` 文档写得很清楚:关闭线程句柄**不会**终止对应线程。

于是整个链条闭合了:

```mermaid
sequenceDiagram
    participant M as 初始化线程
    participant W as 音频读取线程
    M->>W: CreateThread,立即可运行
    M->>M: SetThreadPriority 成功
    M->>M: SetThreadAffinityMask 失败(错误 87)
    M->>M: CloseHandle 并清空句柄
    Note over M,W: 关掉句柄不会让线程停下来
    M->>M: 初始化失败,进入清理流程
    Note over M,W: 句柄没了,后面的等待被跳过
    W->>W: 通过已经失效的对象做间接调用
    W->>W: 目标地址不可执行 → 0xC0000005
```

**这也顺带解释了那个"偶尔进得去但没声音"的诡异现象**:线程调度和内存复用有时间差。初始化失败时,声音引擎处于未就绪状态→没声音;而那个还在跑的线程会不会马上撞上失效地址,要看时机——撞上就闪退,没撞上就放你进去,但依然是静音的。

一个机制,两种表现。到这一步,之前所有零散的现象第一次被同一套解释串起来了。

8 字节补丁

既然BUG已经找到,那肯定要写补丁的了。既然触发点是”音频线程显式绑定核心失败”,那修复思路就很自然:别让它显式绑定。有意思的是,这个 DLL 自己就有这个分支——它的线程创建逻辑里,掩码为 0 时会直接跳过 `SetThreadAffinityMask` 调用,走正常的系统调度。

// 原来的导出函数(简化)
if (properties != nullptr)
    properties->dwAffinityMask = suppliedMask;

// 补丁后
if (properties != nullptr)
    properties->dwAffinityMask = 0;   // 0 = 不显式绑定

具体改动:

```text
函数 RVA:  0x121F0
文件偏移:  0x115F0

原始:48 85 C9 74 03 89 51 04 C3 CC CC CC CC CC CC CC
补丁:48 85 C9 74 07 C7 41 04 00 00 00 00 C3 CC CC CC
```

怎么才算真修好?

然后就是GPT雷霆大验证了

这一步很重要,因为前面吃过"改完能进就算好了"的亏。所以这次定了**更严的通过标准**:

| 验证项 | 结果 |
| --- | --- |
| 原始 DLL 动态跟踪 | 绑定失败(错误 87),随后崩溃——**复现了故障** |
| 只缩小掩码 | 仍然失败——**否掉了错误假设** |
| 进程内取消显式绑定 | 通过音频初始化,进入后续场景 |
| 写入补丁后**普通启动**(无调试器、无运行时钩子) | 通过 |
| Windows 音频会话检查 | 活动、未静音、音量 100%,**检测到非零音频电平**(3 秒采样峰值 ≈ 0.01062) |
| 最后一次进程退出 | 我主动关的,不是闪退 |
| 安装 / 重复安装 / 还原 | 往返测试通过,还原后哈希与原件一致 |

两个细节值得单独说:

- **"普通启动"是关键。** 只在调试器下能跑通说明不了任何问题——普通启动也通过,才排除了"调试器掩盖了异常"。
- **"非零音频电平"比"看到游戏画面"强得多。** 检测只读取该游戏进程的音频会话状态和电平,不录音、不碰麦克风。它证明的是**游戏确实往 Windows 音频管线里送了声音信号**。

**但我也必须说清楚这个补丁没有解决什么:**

- 我**没有**搞清楚宿主机为什么拒绝这个游戏线程的绑定。这是绕过触发条件,不是根因修复。
- 没有完成长时间、全流程的游玩测试。
- 取消显式绑定可能改变性能特征(显式绑定时可能有它的性能目的)。
- 它**不是**"奥日 2 闪退通用补丁"。只对**特定 DLL 构建的特定故障路径**有效——安装器会校验完整 SHA-256,哈希对不上就拒绝执行。

对比一下,GPT明显喜欢直接干软件原理,而ds更是被国内ai营销号那一套通用排障给驯化了一点?不过也不怪他就是,毕竟小模型。

事后总结

首先,Agent真是太好用了!不过也别全相信ai……
蓝色大肥鱼还是依旧吃白饭,不过看看账单 也没法发火。
技术上,首先这一套定位流程还是没问题的,控制变量有一些缺陷但也不是不行。
不过,还是有些可以改进的地方:
1. 过于轻信ds对于Wwise和streaming I/O device的描述,我该上网查的
2. 还是简单只看相关性而不是看因果。改变内存布局/禁用steam虚拟扬声器情况好一点了,于是宣布了修复,逻辑不够完备。在自身实力或者ai足够强的时候,还是需要一些打破沙锅问到底的精神,而不是祈求他机魂大悦次次能玩,留下悬案。
3. 相信转储这类,而不是文本。文本说”写入冲突”,转储说”执行违规”——两条线索指向完全不同的方向。二进制不会为了可读性美化自己。
4. 换显卡还是崩、更新驱动没解决、进去之后依然无声——这些反例一出现,就该把”显卡是主因”的优先级往下压,而不是继续找理由维持它。不要见到A卡就怪他。
5. 修奇奇怪怪Bug最好换大模型,见多识广真不一样

那么最后,也是附上了补丁,如果你和我碰到了同样的问题,那就自取吧

http://git.serversalem.top/Kitasami_Nya/win-troubleshooting-notes-public/releases/download/ori2_fix_v1.0.0/fix.rar

win-troubleshooting-notes-public/ori-wotw-troubleshooting 位于 main – win-troubleshooting-notes-public – Gitea: Git with a cup of tea

留言

您的邮箱地址不会被公开。 必填项已用 * 标注