You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
12 KiB
12 KiB
2023年03月06日 皮蛋 初版未完成 2023年03月16日 皮蛋 继续写,未完成
软件说明
- dnSpy是一个反编译软件,它可以反编译骑砍2或者模组的代码。
- 使用dnSpy可以运行调试骑砍2。
- 如果需要调试的模组拥有代码功能,且是自己的模组,拥有代码源文件,则应使用Visual Studio软件(待建立wiki页面)。
- dnSpy无法捕捉的一些问题
- xml格式或内容错误导致的创建存档或载入存档时的报错。
- 此时应检查骑砍2自弹窗,骑砍2自己会列出xml的具体错误。
- 若不详尽,则应尝试回退文件版本,或使用二分法等,排查出错的具体文件,乃至文件内的具体位置。
- 为避免崩溃或错误累积导致的排查难度骤增,应在完成部分xml内容后就进行测试,多测试,早发现早解决。
- 游戏引擎在渲染画面时产生的错误。遇到此种情况时,就算使用dnSpy调试,仍然会弹出骑砍2自己的报错白框,或闪退。
- 应对新模型和新场景等资源进行详尽的测试,避免此类无法检查原因的崩溃的累积。
- 在代码运行的过程中,部分存在问题的参数不引发崩溃或报错,但传入引擎后引发崩溃或报错。
- 此时难以追踪导致崩溃的原因。
- 应积极测试,遭遇此类崩溃的时间越早,追踪难度越低。
- xml格式或内容错误导致的创建存档或载入存档时的报错。
配置dnSpy
下载dnSpy
- 下载dnSpy并解压缩至找得到的路径。
- 打开dnSpy.exe
导入dll文件
- 只有首次使用时需要导入dll文件。每次打开dnSpy都会自动读取导入后的dll文件。
- 打开骑砍2路径。
- 进入路径Mount & Blade II Bannerlord\bin\Win64_Shipping_Client。
- 在文件夹中,选择按类型排列文件,或选择按名称排列文件。
- 选中所有的“TaleWorlds.”开头的dll格式文件。
- 拖动所选全部dll文件,至dnSpy的左侧界面“程序集资源管理器”中。完成根目录中的导入。
- 进入路径Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client。
- 同⑤,导入所有Native中的dll文件。
- 按照同样的方法,导入剩余的骑砍2原版dll文件,应包括“SandBox”“SandBoxCore”“StoryMode”等。
- 按照同样的方法,导入需要测试的模组的dll文件。特别注意的是,测试模组时不能使用创意工坊订阅的方式来安装模组,应取消订阅,改用手动安装至Modules文件夹的方法进行测试。
设置启动参数
- 单击dnSpy上方菜单栏中的“启动”选项。
- 在弹出的“调试程序”窗口中,单击“可执行程序”右侧的“...”。
- 在弹出的“打开”窗口中,进入你的骑砍2路径,进入Mount & Blade II Bannerlord\bin\Win64_Shipping_Client。
- 在该路径下选中“Bannerlord.exe”打开。
- 填写参数。
- 参数的范例
/singleplayer _MODULES_*Native*SandBoxCore*CustomBattle*Sandbox*StoryMode*需要测试的模组1的id*需要测试的模组2的id*_MODULES_
- 参数的说明
- 按照顺序说明
- 单机模式填写“/singleplayer”,联机模式填写“/multiplayer”。
- “MODULES_”不作任何修改。
- 从第一个“*”开始,依次按顺序填写加载的模组的id。
- 在启动器中排列在上的模组,在参数中应靠前/靠左。也就是越靠前/靠左,加载越早,按从左往右的顺序加载。
- 模组的id在每个模组根目录的SubModule.xml中获取。通常在第三行。是“Id value”里面的值。
- 每个模组id之间用“*”间隔。
- 加载的模组填写完毕后,用"*"结束,然后以"MODULES_"作结尾。
- 总之,通常情况下,只需要复制该参数,并修改里面需要加载模组即可。
- 建议将完成的参数复制并粘贴至找得到的地方保存。每次打开dnSpy都需要重新填入参数。若测试的模组完全相同,则每次粘贴即可。
使用DnSpy启动游戏
- 完成以上步骤后,单击“调试程序”窗口中的“确定”选项。游戏启动。
测试说明
- 测试本身不能解决问题,测试找到了问题的原因也不一定能解决问题。
- 在制作各种内容的过程中,务必仔细按照规范认真制作,不应该因为可以进行测试排查问题而放任可能出现的问题产生。
- 这是由于:
- 存在的问题不一定都以明显的出错形式体现出来。如果出现的问题不明显,没有被发觉,它会在模组中长期存在,甚至在中后期引发恶性坏档。以至于多年后随着内容量增大变得纠缠不清无法排查出问题所在,变成永久的暗病。严重的会使得模组错误崩溃或坏档但无法找到原因最终导致不可玩。
- 测试花费的时间和精力是不可预估的,测试能否找到问题的原因是不一定的,找到了出错的原因能否修复是不一定的。综上,务必从制作的源头避免问题的产生,能极大地减少后续的工作量。
- 除了美术外,在骑砍2上制作内容一定会产生问题,这是不可百分百避免的,要多测试,每做一部分就进行测试,减少问题的累积,从而减少排查难度。
- 完成内容的制作和测试后要认真填写推送内容并推送至仓库或发送至负责人,减少问题的排查难度。
- 以一个实际的案例说明:
- 在希绝大陆的制作中,Culture文化中某文化的元素melee_elite_militia_troop精英近战民兵的值填写了一个不存在的NPCCharacter兵种元素值。
- 创建新存档或载入游戏存档不会因此报错,因此通过了xml填写格式测试。
- 由于骑砍2自己的玩法设计上,精英民兵的产生是罕见但可能的,所以游戏运行短期的稳定性测试可以通过。
- 基础功能测试也可以通过,包括所有的战斗相关、物品与兵种相关都正常。
- 综上,该问题成为未被发现的暗病,长期存在。
- 问题的端倪出现在每次测试运行存档40至120天时,游戏随机崩溃,并且坏档。
- 为了找到崩溃坏档的原因,我需要复现并定位问题,提交复现存档,然后程序才可能找到原因。
- 由于崩溃坏档是在不固定天数出现的,且每次存档需要运行平均80天,这花费了大量的时间精力。
- 幸运的是,这个崩溃是一个必定会出现的问题,所以我可以复现它,并定位到一个准确的崩溃存档,用以提交给程序排查具体原因。如果它是一个不一定会出现,有一定概率才出现的问题,复现并定位所需要的时间可能要翻好几倍。
- 最终程序发现是游戏生成了一个不存在的兵种导致的崩溃坏档,但生成的原因未知。
- 程序返回给我生成出的兵种id,这是幸运的,因为不一定所有的问题都能找到罪魁祸首的id值。假设没有id值,只知道是某个兵种出了问题的话,我需要在自己制作的几百个兵种中找到原因,但这是错误的方向,因为兵种没有问题,问题在文化里填写了不存在的兵种值,是兵种延伸出来的部分。所以通过程序提供的“生成的兵种有错误”信息,要继续排查到骑砍2什么情况下生成兵种,有什么地方会生成可能会出错的兵种,在代码里生成兵种的情况有几百上千种,这无异于大海捞针。如果没有定位到一个具体的问题,只能通过猜测问题所在尝试解决,那么后续的测试每次都要运行多个长达100-200天的存档来验证问题是否被消除,否则重新猜测并解决。这会是噩梦级的后果。
- 我通过id发现该id在Culture文化中填写,但不在NPCCharacter兵种中存在,是一个填错了的id。
- 解决该问题花费了多人十几个小时的工作量。
- 不解决的后果是模组在玩到一定程度后百分百坏档。
- 发现的原因是我在制作的间隙花费了大量的时间进行存档运行稳定性测试,在闲置电脑上挂机多个存档试图验证稳定。如果不进行这样的测试,只能是发布版本后由小部分会玩到游戏天数80天后的玩家坏档,并且这小部分玩家里有个别玩家正确且积极地反馈问题并发送存档,才能引发重视。
- 问题的起因是在一处xml文件中填写了一个错误的id,具体来说,是没有使用复制正确的id并粘贴的方法填入的,用的是错误的、不符合规范的手敲键盘方法填入的。
- 如果与程序为实现功能而创作代码时进行的测试有冲突,应以程序的测试方法为准。
- 此处的测试是针对骑砍2具体使用情景的测试。
- 不同原因导致的崩溃会有多种情况,解决方法也不同。
测试流程
接收问题
- 如果是针对当前版本模组的完整稳定性测试,见测试模组页面(待建立)。
- 如果是接收一个明确存在的崩溃或错误,则需要收集对应的信息。
- 若存在第三方反馈者,则要求反馈者提供
- 必须提供
- 骑砍2版本号
- 模组版本号
- 是否使用其他模组
- 是否使用第三方修改器
- 崩溃的过程
- 崩溃发生在什么操作时/前/后
- 能否重复操作使该崩溃再次出现?如何操作?即复现
- 最好能提供
- 崩溃过程的录像视频
- 崩溃的存档文件
- 若存在第三方反馈者,则要求反馈者提供
- 非第三方反馈者则需记录并将信息一并发送给测试者。
错误的复现
- 通过某种流程操作,使错误再次发生,称为复现。
- 崩溃问题的复现,则在使用dnSpy启动游戏之后,使崩溃发生,dnSpy会跳转至崩溃所在的代码行。
- 此时可以通过各种手段来进一步检查问题原因:
- 阅读代码,通过此处的代码在做什么来找线索。
- 找到该部分可能出错的值或参数等内容,通过断点等方式再次复现,在崩溃前检查值的情况是否异常,是否出错。
- 通过分析类或方法,检查出错的数据是在哪里传入的。
- 等等。
- 找到准确线索后,分析如何解决,找到对应的负责人解决问题。例如,代码有Bug,找提交的程序;值是错误的,找值的来源,或许是xml里填写的错误或xml里缺失的数据,找数值策划或xml填写者。
- 若是自己的模组代码出现问题,dnSpy的反编译并非开发环境,可能调试自己的代码有困难。应配合使用Visual Studio软件来检查错误(待建立wiki页面)。
- 有时崩溃无法跳转至崩溃所在行,有可能是xml文件内容格式不对或渲染层面的问题,需要通过复现方法来推测错误的原因。
- 有时崩溃是骑砍2自己的问题,不一定是由于模组的修改所导致的。
- 有时崩溃是在骑砍2自己的代码上崩溃,但是错误的值出现是因为模组中的某些部分出现了不符合骑砍2情况的数据。
- 有时崩溃无法复现,需要测试成员或反馈者协助明确崩溃的情境。
- 争取获得一份复现崩溃的存档,但要验证存档环境,包括版本号、使用模组、是否进行过修改器修改等。
- 此时可以通过各种手段来进一步检查问题原因:
- 非崩溃问题的复现
- 难以归纳,最好要求反馈者提供视频录像和全部信息,能按照操作步骤复现最好。
断点
- 单击代码的行的左侧,会出现一个红点,这就是断点。
- 代码运行严格按照行的顺序,一行一行地运行。
- 当运行至断点的行时,程序会暂停,此时可以在下方的“局部变量”栏内检查断点时的所有信息,来找出错的线索。
- 如果红点是空心的,说明该无法运行到该行。
- 通过右键断点,单击设置,可以使用断点设置来自动输出运行至此行代码时某项参数的值。用于抓取会被大量运行的行的低概率出错数据。具体方法需要程序补充。
- 通过单击上方菜单的“继续”来使代码继续运行。
- 通过F10键来使代码运行至下一行。
报错发生
- 待写
检查信息
- 待写