1. 为什么选择JetBrains Rider开发Rimworld Mod
作为一个从Visual Studio转投Rider的老Modder,我深刻理解新手在选择开发工具时的纠结。Rider给我的第一印象是"快"——启动速度快、代码补全快、重构快。特别是在处理Rimworld这种包含大量第三方库的项目时,Rider的智能提示能让你少打一半的字符。
Rimworld Mod开发本质上是对游戏进行C#扩展,需要频繁引用游戏核心库。传统VS虽然也能胜任,但在处理跨平台项目(比如同时开发Windows和Linux版Mod)时,Rider的解决方案更优雅。实测在加载Assembly-CSharp.dll这种大型库文件时,Rider的索引速度比VS快3倍不止。
另一个杀手级功能是Rider内置的IL反编译工具。当你想参考原版游戏代码逻辑时,直接F12跳转到dll定义,就能看到反编译后的代码(虽然有些混淆),这比用dnSpy等外部工具方便太多。我最近开发的一个作物生长Mod,就是通过反编译VegetationGrid类搞懂了原版光照计算逻辑。
2. 开发环境搭建
2.1 安装必备软件
首先去JetBrains官网下载Rider(建议选择2023.2及以上版本)。安装时记得勾选".NET桌面开发"和"Unity游戏开发"两个组件,这会自动安装必要的.NET SDK。安装完成后别急着启动,我们还需要:
- Rimworld游戏本体(建议Steam版)
- 游戏目录下的关键dll:
- RimWorldWin64_Data/Managed/Assembly-CSharp.dll
- UnityEngine.dll
- UnityEngine.CoreModule.dll
把这些文件路径记下来,稍后要在项目中引用。有个小技巧:在游戏目录创建"ModDevelopment"文件夹,专门存放开发用的dll副本,避免误操作影响游戏运行。
2.2 配置Rider首选项
首次启动Rider需要优化几个设置:
- 在Editor → Code Style里将命名风格改为PascalCase(Rimworld标准)
- 关闭Solution Wide Analysis(大型项目会卡顿)
- 开启Allow runtime decompilation(反编译必备)
特别建议安装两个插件:
- HarmonyX - 方便查看Harmony补丁
- XML Tools - 处理Defs文件的神器
3. 创建第一个Mod项目
3.1 新建类库项目
点击New Solution → Class Library (.NET Framework),注意选择.NET 4.7.2(与Rimworld运行时一致)。项目命名建议遵循"作者名.功能名"格式,比如"Mechanoid.DroneControl"。
创建完成后立即做三件事:
- 删除自动生成的Class1.cs
- 创建Mod主类(如DroneControlMod.cs)
- 添加About文件夹和About.xml
// DroneControlMod.cs示例 using Verse; namespace Mechanoid.DroneControl { [StaticConstructorOnStartup] public class DroneControlMod : Mod { public DroneControlMod(ModContentPack content) : base(content) { Log.Message("DroneControl Mod loaded!"); } } }3.2 引用游戏库
右键项目选择Add Reference,添加之前准备的三个dll。关键设置:
- 取消勾选"Copy Local"(避免打包冗余文件)
- 将Specific Version设为False(兼容性更好)
有个Rider独有技巧:按住Ctrl点击using语句中的类型名,会自动提示添加缺失的引用。我开发武器Mod时,这个功能帮我快速找到了Projectile类的所在库。
4. 开发实战:制作一个简单Mod
4.1 添加新物品
我们以添加一个侦查无人机为例,需要完成:
- ThingDef定义(XML)
- 纹理文件(PNG)
- 可选的行为逻辑(C#)
先在About/Defs下创建Things_Weapons.xml:
<?xml version="1.0" encoding="utf-8"?> <Defs> <ThingDef Parent="BaseThing"> <defName>Drone_Scout</defName> <label>侦查无人机</label> <description>可自动巡逻的轻型无人机</description> <graphicData> <texPath>Things/Drone/Scout</texPath> <graphicClass>Graphic_Single</graphicClass> </graphicData> <statBases> <MarketValue>350</MarketValue> </statBases> </ThingDef> </Defs>Rider的XML智能提示会基于XSD自动补全标签,这是我放弃VS的重要原因之一。按Alt+Enter可以快速格式化混乱的XML。
4.2 实现特殊功能
让无人机每小时自动扫描周围敌人:
public class CompDroneScanner : ThingComp { private int ticksUntilScan; public override void PostSpawnSetup(bool respawningAfterLoad) { ticksUntilScan = 2500; // 1游戏小时 } public override void CompTick() { if (--ticksUntilScan <= 0) { ScanEnemies(); ticksUntilScan = 2500; } } private void ScanEnemies() { var map = parent.Map; var enemies = map.listerThings.ThingsInGroup(ThingRequestGroup.AttackTarget); if (enemies.Any()) { Find.LetterStack.ReceiveLetter("无人机警报", $"发现{enemies.Count}个敌对目标", LetterDefOf.ThreatSmall); } } }在Rider中按Ctrl+Shift+Alt可以快速查看方法调用层次,这对理解复杂交互特别有用。比如查看LetterStack的调用链,能避免与其他Mod的冲突。
5. 调试与打包技巧
5.1 调试配置
在Rider顶部工具栏点击"Add Configuration",选择"Executable":
- 路径:指向RimworldWin64.exe
- 工作目录:游戏根目录
- 参数:-allow-multiple-instances
设置断点后按Shift+F9开始调试,游戏启动时会自动附加调试器。有个实用技巧:在Mod构造函数设置条件断点,只在你测试的特定Mod触发。
5.2 智能打包
传统方式需要手动复制文件,用Rider可以创建Post-build事件自动完成:
<!-- 在.csproj文件中添加 --> <Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Exec Command="xcopy /y /s "$(TargetDir)*.*" "..\..\RimWorld\Mods\$(MSBuildProjectName)\Assemblies"" /> </Target>更专业的做法是用MSBuild任务自动生成About.xml版本号:
// 在Mod主类中添加 public static readonly string Version = typeof(DroneControlMod).Assembly.GetName().Version.ToString(3);6. 高效开发技巧
6.1 代码模板
Rider的Live Template能极大提升效率。比如创建新ThingComp时,输入"comp"按Tab会自动生成完整模板。我自定义了几个常用模板:
- harmony - 快速生成Harmony补丁代码
- def - 创建新的Def类
- comp - 生成CompProperties模板
6.2 反编译技巧
遇到不熟悉的原版方法时,用Rider直接反编译:
- 光标定位到方法名
- 按F12或Ctrl+B
- 在反编译视图按Ctrl+F12查看方法层次
特别注意灰色代码(无法反编译的部分),这些通常涉及Unity底层调用。我研究作物生长时发现,原版的GetGrowthPerTick方法就包含这种"黑箱"逻辑。
6.3 性能优化
大型Mod容易引发性能问题,Rider的内置性能分析器能定位热点:
- 运行性能分析(Alt+Shift+F10)
- 执行测试用例
- 查看耗时最多的方法
最近优化我的工厂Mod时,发现MaterialCache.GetTexture占了60%耗时,改用静态缓存后帧率提升了15%。