前排注释:
转载时,请在显著的位置标明作者小莫以及本贴地址
- 上方目录点击可进行翻页
- 所有内容已经在我的博客更新完毕:https://www.aoe.top/mod/434
- 如果你对Mod的制作感兴趣,可以考虑申请加入我们的Mod组:https://bbs.3dmgame.com/thread-5838764-1-1.html
- 如果我有任何写错或者遗漏的地方,欢迎大家随时指出;
- 如果你有任何不懂的地方,欢迎留言,我有空会进行回复;
摘要自宵夜97:https://www.bilibili.com/read/cv8997376
两者的相同点:
UMM和BepInEx都使用Harmony库作为核心来对游戏进行功能修改。两者的不允许游戏路径出现中文或其他特殊符号,所以请保证游戏安装在纯英文路径。
两者的不同点:
UMM使用一个单独的exe程序来安装Mod环境,此程序基于.Net,需要玩家电脑安装.Net4.5之后的版本才能启动。Mod环境的安装有两种方式,一种是直接修改程序集来加入环境,一种是通过UnityDoorStop在游戏启动时加载Mod环境,第一种方式因为破坏了游戏原有的程序,所以每次游戏更新的时候,都会导致Mod环境丢失需要重新安装,第二种方式不会破坏游戏的原有程序集,所以不会因为游戏更新而丢失环境。在Mod安装方面,UMM也有两种方式,一种是直观的,将Mod压缩包拖动到安装器内来安装,另一种是手动解压Mod包,放到正确的路径。UMM还内置了一个Mod管理界面,在游戏中按Ctrl+F10可以呼出管理界面,修改Mod配置、开启关闭Mod等。
BepInEx没有单独的exe程序,环境的安装只是需要将BepInEx解压到游戏根目录即可。插件的加载方式上,等于UMM的第二种,也是通过UnityDoorStop来运行时加载。插件的安装方式上只有一种,将插件解压到指定的目录下(BepInEx/plugins)即可,没有UMM要求目录那么严格。BepInEx本身并不含有可视化的插件管理等功能。





本章中的部分内容参考了:
- MOD制作教程 : 如何从零开始制作一个Unity Mod Manager MOD - By:JKstring
- Unity游戏Mod/插件制作教程07 - Harmony补丁基础 -By:宵夜97
注意:
1.我们的函数需要使用static静态函数,不然会报错;
2.函数名可以自定义,但尽量不要和游戏原有函数冲突;
3.两种拦截方式大同小异,希望大家举一反三。
注释:
1.Mecha __instance中,"Mecha" 为当前类的名称,"__instance"为Harmony的固有写法(有两个“_”);
2.这种方法只限于操作公共public变量和函数;
来自 https://bbs.3dmgame.com/thread-5870433-1-1.html
关于Traverse的使用:
Traverse是harmony类库下的一个工具类,也就是在一开始引用的using harmony;这条语句后,方便我们使用的一个类,首先我们要明白private和public还有protected三个关键词的区别,具体可以百度,我这里仅从结论讲明,除了public,其他的private和protected从外界是无法访问到的,但是用Traverse类不管它是public,private,protected,均可以强行访问,为什么不任何地方都使用Traverse去访问呢,因为性能问题,用Traverse要走映射,简单来说运行速度会有些许影响
Traverse的具体使用方法简单的来说明一下,Traverse.create(类的实例),表名我要将一个类的实例转为Traverse对象,简单来说就是附加功能,比如我们以前都是自己买菜,后来有了XX外卖,我们不需要亲力亲为了,XX外卖就等于Traverse对象了(这里就是将映射功能简单化了,不需要自己打代码了),这样我们就有一个可以访问类实例的Traverse对象了,在上面法宝的例子中,我是直接写为了
var itemID = Traverse.Create(__instance).Field("itemID").GetValue();
这是一种简化的写法的,下面我分开并且逐步注释一下
Traverse t = Traverse.Create(__instance);//根据__instance (ToilRefining类的实例) 创建 Traverse对象,并且用t表示
Traverse f = t.Field("itemID");//在ToilRefining实例里面有个itemID的字段,找到他并且创建一个Traverse对象,用f表示,这样可以强行访问 itemID,因为itemID是私有的没法直接访问
int itemID = f.GetValue();//将Traverse版本的itemID提取成可以直接访问的数值,因为Traverse并不知道原本itemID是什么类型的,所以我们要用标注这是个int类型了,从源代码中我们可以知道itemID的变量类型,对应修改即可
于是我们就访问到itemID了
既然有获取,自然就有修改,修改我们可以用f.SetValue(数值),这里就不需要指定了,因为你在输入数值的时候,他会自动把你输入的数据转成对应的类型
这里我说一下字段,属性,方法的意思,这是C#的基础,字段代表类变量,可以理解为类中的全局变量,可以再类中任意地方访问到
属性是字段的升级版,他在源代码中的样子是这样的
他跟字段的定义差不多,但是后面会有括号,里面还有set和get,这种样子的就是属性,我们不能通过Traverse.Field(字段名字),而是通过Traverse.Property(属性名字)来访问,如果定义中只有get,表名这个东西只能获取,不能更改(就是游戏开发者也不能),get和set都在就是可以获取也可以更改
最后就是方法,在C#中称为方法,C语言中称为函数,比如游戏源码中,MakeFaBao就是制作法宝的方法,他定义时后面跟随的是()这种括号,我们想要访问游戏private的方法可以用Traverse.Method(方法名字).GetValue()来运行,注意后面要加上.GetValue(),因为仅仅Traverse.Method(方法名字)是获取的方法的Traverse对象,而没有运行他
C#中有一个关键词是var,这个关键词是这个变量是智能根据你后面赋值来判断他的变量类型的
比如 var a = 6;//a是int类型
var b = "我是文字";//b就是string类型的
于是之前为了itemID那么多行的代码就可以省略为var itemID = Traverse.Create(__instance).Field("itemID").GetValue();一句话搞定
当然也可以var t = Traverse.Create(__instance);
var itemID = t.Field("itemID").GetValue();var XXXX = t.Field("XXXX").GetValue();
来多次获取








结语
GUILayout还可通过GUIStyle来为控件制作样式,但这部分我还研究的不够升入,我只会制作一些简单的样式(比如说设置背景颜色,固定宽高等,这些可以在vs中直接看到相关参数),等我研究出更加深入的样式后,可能会更新续篇。
到现在为止,BepInEx的教程系列就算完结了,感谢大家的游览和阅读,希望你能成为Mod领域中的一座大山,造福更多的玩家。
httniklaus 发表于 2021-2-22 08:38
博客打不开,这里就写完了?

呢。。。
| 欢迎光临 3DMGAME论坛 (https://bbs.3dmgame.com/) | Powered by Discuz! X3.2 |