UnityEngine.Random rand = new UnityEngine.Random();
唯独这个没法解决:
CS1061 'TimeManager' does not contain a definition for 'm_Timescale' and no accessible extension method 'm_Timescale' accepting a first argument of type 'TimeManager' could be found (are you missing a using directive or an assembly reference?) main.cs 33
CS0168 The variable 'm_Timescale' is declared but never used main.g.cs 220
dnspy 默认不具备 unity 调试功能,所以需要自己动手
下载必要资源
dnspy 32 和 64 位的都要准备,然后放到一起,我分别命名为
32
和64
众所周知 dnSpy/dnSpy 早已不受支持,但社区依旧在维护 dnSpyEx/dnSpy
按需取用
这里有 unity 的调试库
Releases · liesauer/Unity-debugging-dlls
下载然后再放一个文件夹,我将其命名为
unityLib
让游戏可以被 dnspy 调试
要让游戏可以调试,首先需要知道一些关键信息
信息收集
判断编辑器、mono版本和替换库
unityLib
中的 dll 是供调试用的,替换对了游戏才能正常启动判断编辑器版本
有源码的看
ProjectSettings\ProjectVersion.txt
没有则可以通过主程序的详细信息判断,如果不是日期,那就直接是编辑器版本
如果是一个日期,那就需要多方查证了,确定它是编辑器的构建日期还是游戏的构建日期,但大体可以确认是那个时期的东西
最稳定的方法是以文本编辑器方式打开资源文件夹里面的
unity default resources
文件,看第一行给的是什么,那大概率就是那个了判断 mono 版本
用 dnspy 打开
mono-2.0-bdwgc.dll
或mono.dll
,通过文件的时间戳判断大致的版本下面会提供两种方法,让 dnspy 可以调试所有版本的游戏
给 dnspy 开调试接口
替换 mono 文件
从
unityLib
中抽取文件,替换游戏的mono-2.0-bdwgc.dll
和mono.dll
dnspy 只提供了 2019 及以前的 mono,可现在都 2023 了,unity 编辑器的 LTS 都 2021 了,自己编译需要一大堆东西......还是另找出路吧
使用 UnityDebug
Sl4vP0weR/UnityDebug
根据 readme ,首先安装 .net 库,包括 .NET SDK 7+ 和 .NET Runtime + SDK 4.8 ,还有 visual studio(2022 + .net multiplatform + .net 桌面开发 + 使用 Unity 的游戏开发)
网络问题可以尝试改 host ,改 DNS......
然后选择 cpu 和系统并构建
报这个是因为文件夹只读或者没选 cpu 和系统,去改一改
然后重新生成解决方式,重新生成
好了,弄了这么半天,终于看到了曙光
现在,把 Win_x64 (总之就是之前选择好的 cpu 和系统)里面的东西复制到游戏根目录
重复一遍,复制内容不是复制这个文件夹
调试之前
弄完了这些,现在快要进入正题了:如何去测试一个游戏?
这里以 Cuisineer Demo 为例,因为前阵子正好下了它的 demo ,没来得及玩厂商就把游戏测试下了,不过游戏还躺在硬盘里面,不用 steam 授权也能直接开
下面是可以直接收集到的信息:
既然是 2020 的编辑器,那就需要用刚刚构建好的项目来进行调试
准备调试
添加环境变量
写成脚本就是这样的
把脚本保存,管理员权限执行就可以了
准备连接
unityDebug 默认端口 56000
dnspy 选择 unity(连接)
连接
127.0.0.1:56000
如果位数不对,程序会报错崩溃,但如果看到底下的橙框,就说明成功了
游戏测试
unity 游戏的主要逻辑都在
Assembly-CSharp.dll
有的游戏不这么干,而是生成额外的 dll ,但记住这点就好:代码最有可能放在文件大小最大的那些文件里面(排除 unityplayer.dll 等依赖)
搜索 .dll ,然后按大小排列,不出意外前几个文件就能“中奖”
当然了,激活了 mono 功能的 cheat engine 也很重要
还要记得备份文件!
选择 mono dissect ,根据之前游玩的经验查找最有价值的类
这次 dnspy 一拆,发现函数都在
{-}
里面卡住时间
游戏中,1 小时等于 60 秒,我希望时间慢点
找到 timemanager ,发现时间流逝的代码
update 函数,一秒执行一次
发现了这两行:
敲断点,准备调试
游戏马上停下来了,但音乐播完了一轮才停,有趣但无关紧要
同时还知道:时间在有暂停标记时会直接返回
那思路就是:通过某个按键,调用触发时间暂停标志的代码,让这个函数直接返回
如果是 public 函数的话,自己编写代码,然后用 SharpMonoInjector 通过外部 dll 注入也是可以的,但 private 的话就给直接修改这部分了
修改代码
选择 update 函数,右键编辑函数
新窗口会红很多东西
如果是
using System;
这样的代码红,把模块引入一下左下角有一个文件夹图标,点击它,将模块所在的文件添加进去
还红了一堆类成员:
m_TimeSeconds
m_Timescale
m_SecondsTimer
m_MidnightWaitingForCutscene
m_CurrentTimeHours
m_CurrentTimeHours
m_SecondsTimer
m_MapTimeFrozen
有一些是这样的:
改成这个形式就可以了:
random 函数错误
因为 dnspy 不知道该用
UnityEngine.Random
和System.Random
中的哪一个。添加如下代码即可解决唯独这个没法解决:
在类中的私有变量,又同时出现没有定义和声明了没有使用,可能是 dnspy 的问题吧......
其他的游戏还是可以修改的
就这样吧,我真是找了个大坑给自己跳