上周有位读者私信我,说照着第一篇的教程搓了个新单位,改完攻击力扔进游戏,新鲜劲儿一过就不知道干嘛了。想让这个单位在特定地形加战斗力、想让某栋建筑在城市有学院时多给两点科研、想让领袖有自己的议程……结果一翻文件全是白纸。这个感觉我太熟了。第一次用XML写出能跑的mod,只能算摸到了门把手;文明6真正的modding大门,是从你开始面对它的数据库和Modifier系统才打开的。这篇第二篇不讲废话,直接从数据层、逻辑层、调试工具三块带你把整个链条过一遍,目标是让你能独立做出一个带自定义能力、自定义议程和出生地倾向的完整文明mod。这篇的东西偏硬,但都是我做mod时天天在用的东西。
1. 从XML到SQL:为什么第二个mod应该开始动数据库
1.1 XML的三个短板,越写越难受
第一篇教的是在ModBuddy里建XML类型的Gameplay Data,往<Buildings>里塞两行<Row>,游戏就读进去了。这套流程对单个物件非常直白,但只要你开始接触真正的mod,很快会撞上三个墙:
第一,XML在游戏加载时只能做插入操作,不能更新、不能删除。你想把原版某个建筑的成本从100改成60,用XML写一个同名的<Row>进去,结果往往是主键冲突,加载时直接红字。就算把原有Tag覆盖对,也要踩一堆坑。
第二,改动量一大,XML的冗余会把人逼疯。每加一条数据都要写完整的父标签和属性名,一个mod几十个物件,文件翻起来比翻通讯录还累。
第三,XML没法写注释和分段执行。你想临时禁用某条数据,只能手动删一大段;想在调试时快速试错,也没有"只执行某一段"这种操作。
Civ6的底层其实是一份SQLite数据库,游戏本身所有数据都存在里面。你用XML改数据,等于拿翻译软件跟本地人对话,能通,但绕。直接用SQL,就是对原始数据库说话。
1.2 同一个改动,SQL比XML短一半还多
拿一个最简单的建筑举例。XML写法是这样的:
xml复制<GameData>
<Buildings>
<Row>
<BuildingType>BUILDING_MY_HOUSE</BuildingType>
<Name>LOC_BUILDING_MY_HOUSE_NAME</Name>
<PrereqCivic>CIVIC_CODE_OF_LAWS</PrereqCivic>
<Cost>90</Cost>
<AdvisorType>ADVISOR_CULTURE</AdvisorType>
</Row>
</Buildings>
</GameData>
换成SQL,一行搞定:
sql复制INSERT INTO Buildings (BuildingType, Name, PrereqCivic, Cost, AdvisorType)
VALUES ('BUILDING_MY_HOUSE', 'LOC_BUILDING_MY_HOUSE_NAME', 'CIVIC_CODE_OF_LAWS', 90, 'ADVISOR_CULTURE');
这还不算完。SQL能直接改写原版数据:
sql复制UPDATE Buildings SET Cost = 60 WHERE BuildingType = 'BUILDING_MY_HOUSE';
这一句在XML里怎么都写不出来。SQL还能用INSERT OR REPLACE、INSERT OR IGNORE处理重复数据,用注释临时屏蔽一块,用分号把逻辑拆得清清楚楚。做mod超过两个版本之后,回看XML,你大概率会感谢自己早换成了SQL。
1.3 直接打开游戏数据库,比啥教程都实在
在Steam库里找到文明6安装目录,下面有一份关键文件:
code复制SteamLibrary\steamapps\common\Sid Meier's Civilization VI\Base\Assets\Gameplay\Data\Gameplay.sqlite
下载一个DB Browser for SQLite,打开这个文件,Civ6的所有数据表结构、字段名、原版所有ModifierType、所有RequirementType全都摆在眼前。我到现在做mod的第一步永远是查这个数据库,而不是翻教程。网上任何攻略写错一个表名,你对着数据库一查就能识破。这个习惯比记住任何ModifierType的名字都管用,因为你不用记,查得到就行。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Modifier链:文明6里"动态加成"到底是怎么算出来的
2.1 文明6所有能力的底层是五张表
很多新手卡在一点:为什么我往Buildings表里写了Yield列,游戏根本不认?因为文明6的建筑、特性、政策产生的"动态效果",并不直接在建筑表里写加成值,而是走一套统一的Modifier系统。这套系统由五类对象串起来:
Types:所有东西的"户口本"。建筑、特性、Modifier、Requirement,凡是游戏里的对象都要先在Types表里登记一个Type和Kind。Modifiers:行为的定义。一行Modifier记录着一个行为的模板和它生效的条件。ModifierArguments:给行为模板填充的具体参数。比如给多少产出、作用于什么类型。Requirements和RequirementSets:触发条件。满足条件时Modifier才生效,RequirementSet是把多个Requirement用AND或者OR组合起来的容器。BuildingModifiers、TraitModifiers、LeaderTraits等挂载表:负责把Modifier挂到建筑、特性或者领袖身上。
拿生活里的事打比方:一条Modifier是一张"补贴政策",参数是"每月发多少钱、发给谁",requirement是"申领人必须满足什么条件",挂载表是"这份政策贴在哪个部门的墙上"。游戏启动时逐条读取,条件满足就发钱,不满足就晾着。
2.2 一个完整的条件加成示例:有学院才加科研
我写一个很典型的例子:造一栋新建筑,如果城市里有了学院,这栋建筑就给城市额外加2点科研。SQL完整写法如下:
sql复制-- 1. 给建筑、modifier、requirement、requirement set登记户口
INSERT INTO Types (Type, Kind) VALUES
('BUILDING_TUTORIAL_HOUSE', 'KIND_BUILDING'),
('MODIFIER_TUTORIAL_HOUSE_SCIENCE', 'KIND_MODIFIER'),
('REQUIREMENT_TUTORIAL_HOUSE_HAS_CAMPUS', 'KIND_REQUIREMENT'),
('REQUIREMENTSET
