修订说明(2026-09-30):本文记录 2026-07-05 的阶段工作。早期代理方案、样本测量和原版算法证据已重新区分,未完成事项按当时验证范围理解。后续进展见高度图还原与POI、Stamp 和植被岩石布局。
AI 协作做游戏 · 资产逆向系列 · 场景地形篇
引子:把关卡打开,先看脚下这片地
前几篇将资产从二进制中提取出来、导入引擎、按坐标复位。完成这些后,一张关卡便能打开了——建筑矗立、货箱散布、树木也已栽种。但将镜头压低,观察脚下这片地,会发现一个更根本的问题尚未回答:这片地本身,是怎么来的?
它不是一张手工雕的高度图。这款游戏有四百多颗星球,没有哪个团队会去手工雕四百多张地形——那是几百人月的美术量,还没法维护。它是「算」出来的:给一套规则、一个随机种子,运行时现场生成一片该有的地貌。这一篇讲的就是这套「算地」的规则——地形块怎么切、高度怎么定、地表材质怎么上色、整套生成数据是怎么组织的。
本文记录的是 7 月初的静态结构分析。类型定义能说明字段和资源关系,当时尚未恢复完整运行时计算。后续工作已经修正了部分解释,尤其是高度类别、静态高度纹理和区域槽位的用途;不能把当时未取得的数据直接认定为加密实体。
先给一张全局的路线图:一颗星球从「一条数据记录」到「一片可玩的地」,中间要经过继承装载、选群系、定天空、生成地形、铺散布、摆任务、运行时装配这一整条流水线。这一篇聚焦其中的「地形」那一段——它是整条线里最能讲透、也最能看出这套「程序化装配」思路的一环。先花一节把地形放回它所在的整颗星球里,再一头扎进地形本身。
一、先看全景:一条记录,怎么变成一颗星球
在讲「地怎么长」之前,先看一眼「一颗星球是怎么被装配出来的」——因为地形不是孤立的,它是这套装配流程里的一环,而这套流程的思路,会一路贯穿到讲植被和建筑的下篇。
整颗星球的生成,本质是一座装配厂:一头是规则库(各种模板、地形区域、群系、天空),一头是一条条「星球记录」(每颗星选哪些规则),中间加一个随机种子,装配出一颗落地可玩的星。
这里有几个数字,能说明这套设计有多「省」:
① 425 颗星球,退化成 29 个等价类。 我把全部 425 颗星球的生成记录拉出来,按「用哪套规则」去重,发现它们其实只归成 29 个原型。换句话说,四百多颗星,是这 29 份配方的反复复用。原型表里能看到它们的样子——森林平原、极地冰川、熔火沙漠、血色丛林、赛博斯坦机械母星……每个原型带着自己的群系、天空、采矿类型和一个布局种子。没有哪颗星球是「从零做」的,它们都是从原型库里领配方、换个种子再撒一遍。
② 靠 inherits 模板复用,把公共规则只存一份。 每颗星球记录里有个 inherits 字段,指向一个模板——「同类星球的公共规则」只存这一份,每颗星自己只记独有的差异(叫什么名字、采什么矿)。实测森林沼泽类一百多颗星共用少数几个模板;而超级地球母星、赛博斯坦、几颗虫巢世界是「独苗模板」各占一份。这套复用的意义是可维护性:策划要调「所有沼泽星的地形规则」,只改一个模板,一百颗星同时生效——不用去动一百张地图。
③ 一颗星球,还能「一星多用」。 最巧的是分阵营自适应:同一颗星,敌人不同,观感就不同。 这不是做三张地图,是同一份数据,运行时按当前敌人换一套雾色和道路:
| 敌人阵营 | 雾色(RGB) | 道路 |
|---|---|---|
| 虫族 | 土黄 [.23, .20, .03] | BugRoad |
| 机械 | 冷灰 [.10, .10, .10] | BotRoad |
| 光能 | 幽蓝 [.15, .46, 1] | IlluminateRoad |
一颗沼泽星,打虫族是弥漫土黄毒雾的巢穴战场,打机械是冷灰工业废土——两种氛围,只占一份星球数据。有限的星球库,靠这套自适应又翻了几倍的利用率。
这三点合起来,就是这套系统「用极少数据撑起整个银河」的底层逻辑——三层解耦:改规则库影响一类星球,改星球记录影响一颗星,改种子影响一局。记住这个「规则 + 组合 + 种子」的骨架,因为接下来讲的地形,正是它在「地」这一层的具体实现;下篇讲的植被和建筑,是它在「物」那一层的实现。
那么这一颗星球的「地」,具体是怎么算出来的?往下看。

二、地形配置与高度输入
最反直觉的一点,先摆出来:这款游戏的地形,不存高度图。
一般游戏做地形,是美术在编辑器里刷一张 heightmap(高度图),每个像素记一个高度,地形网格照着它起伏。这种做法直观,但代价是——每张图几 MB,四百多颗星球就是几 GB,而且每张都得人去刷、去改。这款游戏没有这一层,它存的是一套生成配方:运行时按配方现算,算完才烘焙出地形。
配方由四个环节串起来:
- Voronoi 切块——把一片地平面剖分成不规则的多边形块(像细胞、像龟裂的泥地);
- 高度类别与区域规则——字段记录分类和参数,最终高程还需要来源计算、角点混合、插值与滤波;类别编号不能直接当作米制高度。
- Displacement 位移——用一组参数把块表面细化,加起伏;
- Stamp 印章——用圆形、矩形、样条这些几何形状,往地上盖建筑基座、道路、坑洞。
这四步跑完,运行时把结果烘焙成一张高度图 + 地形网格。注意:高度图是运行时算出来的产物,不是美术画的输入。 换一个种子,Voronoi 的剖分就变了,整片地的布局跟着变——这就是为什么同一颗星球反复刷、每次地形都不太一样。这一点对一款要「重复刷同一批星球」的游戏至关重要:地形不是死的,每局都是新算的。

我剖开这套生成结构(游戏用一套名为 typelib 的类型定义描述所有数据),将与地形相关的类型全部列出核对,验证了一个关键判断:整套地形几何,没有任何一张贴图。
DisplacementComponent(位移组件,632 字节)——里面全是数值和三维向量,还有「爆炸类型」「单位尺寸」这类枚举,没有一个字段是位移贴图;- 当时检查的 Displacement、Stamp 和 Voronoi 类型主要包含数值与几何字段。这能说明这些记录本身的结构,不能据此排除其他资源层级中的高度纹理引用。
SubregionVoronoiCell(Voronoi 单元,144 字节)——是「边」(SubregionVoronoiEdge)加二维坐标,纯几何。
逐项检查 20 个生成类型,是整理接口的起点;没有发现 texture 字段并不能证明整个生成过程不采样纹理。后续已经确认自然 Stamp 与 Location 使用静态高度资产。程序化生成可以组合区域计算和静态局部形状,二者并不冲突。
三、生成数据的层级:从一个区域规则,到每一块地
第一章说了「四个环节」,但它们不是平铺的四步,而是嵌套的一套数据结构。把这套结构摊开,才能看清「一片地」在数据里到底是怎么组织的。
自顶向下是这样一条链:
LevelGenerationSettings(408 字节)——顶层的关卡生成设置,一场关卡的总入口;- 往下是
GenerationRegionSettings(2984 字节,48 个字段)——一个地形区域的完整规则,是这套结构里最大、最核心的一块。它里面挂着子区域、Voronoi 剖分、印章摆放、道路引用、环境效果……一个区域该长什么样,全在这里定; SubRegionSettings(64 字节)保存子区域类型、区域 ID 和SubRegionHeight等规则字段。高度类别用于后续计算分支;仅凭枚举或数组长度,不能确认地图由六个固定高程组成。- 最底下是
SubregionVoronoiCell——子区域被 Voronoi 剖分成的一个个具体单元。

lowland 与 highland 是两个配置槽位,名称不能直接证明它们控制两片独立地形。后续对 431 个 Planet 的审计中,两槽的对应配置一致。区域如何取得空间归属和参与高度生成,需要继续沿配置与运行时计算确认。
再说「印章」(Stamp)这一支,它其实是个完整的家族,不只是一个「圆或矩形」:
| 类型 | 作用 |
|---|---|
Stamp |
单个印章:一个圆或一个矩形 |
StampSpline |
样条印章:沿一条曲线盖(道路、河床用这个) |
StampPlacement(224 字节) |
一次印章摆放:形状 + 位置 + 权重 |
StampGroup / WorldStampGroup |
印章分组:一组印章一起盖(一片建筑基座群) |
StampInfo |
印章信息:Stamp + 权重(StampWeights) |
印章是「往程序化地形上盖确定性内容」的手段——地形本身是种子随机的,但基地要平、道路要连、坑要在该在的地方,这些「必须确定」的东西,就靠印章在随机地形上盖出来。圆矩形盖平台和坑,样条盖道路和河,分组盖成片的结构。随机的底 + 确定的印章,是「程序化」和「可玩性」的平衡点:既要每局不同,又要关键地形可控。
顺带说一下那个最大的 GenerationRegionSettings(2984 字节 / 48 字段)里,除了子区域、Voronoi、印章,还挂着两支值得一提的东西:
RouteSettingReference(道路引用)——一个区域怎么被道路串起来。这跟前面「分阵营自适应」里的 BugRoad / BotRoad 对上了:道路不是画死的,是区域规则引用一套道路配置,运行时按阵营换。EnvironmentalEffectType(环境效果)——这个区域该带什么环境效果(毒雾、沙暴之类)。一个区域的「氛围」也是规则的一部分,不是单独摆的。
一个「地形区域」在数据里,是把地貌规则、切块、印章、道路、环境效果全打包在一起的一个整体。 这也是为什么换一套区域规则,整片地的「地貌 + 路网 + 氛围」会一起变——它们本来就绑在同一个 GenerationRegionSettings 里。
四、高度类别、连续地面与地形块测量
早期把高度类别解释成六级台阶,是一个已经撤回的假设。分类字段决定规则分支,最终高度场仍可以通过插值和平滑形成连续坡面。
不能从六元素字段或高度枚举,推出每个 Voronoi 单元只能取六个高程。Voronoi 的区域边界、邻接与归属可以参与计算,但空间分区不等于地表必须发生台阶跳变。
参考地形可以包含平台、缓坡、山脊与陡坡;这些形态需要分阶段解释,不能全部归因于一个离散高度开关。
地形形态会影响视线、移动和战斗空间,但本文没有证据证明原版通过六档台阶统一决定这些玩法特征。
测量样本包含 56 种方形尺寸,从 23 米到 511 米,常见序列为 31、63、127、255 米。这个序列提示规整的分块层级,但仅凭尺寸统计,不能确认完整的四叉树 LOD 调度方式。
② 顶点密度恒定:每 0.5 米一个顶点。 不管方块多大,密度都一样——一个 31 米的块是 64×64 个顶点,63 米是 128×128,99 米是 200×200。边长顶点数 =(米数 + 1)× 2,无一例外。完美线性,一看就是程序生成的规整网格,没有任何手工痕迹。
③ 起伏以缓坡为主,是「可作战的开阔战场」。 把 1243 个块按高差分类:缓坡(3–10 米)占 42%(主力),微起伏(0.5–3 米)24%,平坦(<0.5 米)13%,中坡(10–20 米)14%,陡峭(>20 米)只有 8%。地貌整体是开阔可战的,不是极端险峻的山地——这也符合一款「大兵团野外作战」游戏的需求:要有起伏做掩体和层次,但不能险到没法机动。
这些测量描述样本的网格尺寸、采样密度和起伏分布。它们可以约束重建结果,却不能反向证明六档台阶是原版生成算法。

五、地表材质:法线资源与颜色参数
讲完地形的形状,讲它的长相——地表材质。这一章有个颠覆直觉的发现,是我这次挖得最意外的一处。
先说地表材质怎么挂。每颗星球属于一个生物群系(biome,就是下篇填充系统里驱动植被的那个 biome),每个群系配一套「地表长相配方」,明文能读,主要字段有:
terrain_material——地表材质(一张贴图的引用);dirt_color——泥土底色(直接写死的 RGB 值);grading_day/grading_sunset/grading_night——昼 / 黄昏 / 夜三档调色(每群系独立);- 还有
shading_environment(着色环境)、terrain_projector(地表投影)、path_settings(道路)等。
我把 16 个群系的这套配方全拉出来,发现地表材质一共 15 张(极地和雪林共用一张)。然后去把 forest(森林)群系那张地表材质贴图提出来看——这里发现了这篇最反直觉的一点。
那张贴图,第一眼看是「绿草、黄土、苔藓、树根」的一张地表纹理图集,竖着叠了 26 层。但我去查它的真实格式,发现它是 BC5 格式——一种只存两个通道(红、绿)的法线贴图压缩格式。也就是说:
这张「看起来是地表颜色」的图,其实是一张法线贴图(记录表面凹凸方向的),根本不是颜色。 我一开始看到的「绿草黄土」,是法线的 X/Y 分量被当成 RGB 显示出来的假色:
- 红通道 = 法线的 X 分量(表面朝左还是朝右);
- 绿通道 = 法线的 Y 分量(朝上还是朝下);
- 蓝通道 = 全是 0,空的——由着色器用
Z = √(1 − X² − Y²)实时算出来。
我把这个蓝通道拉出来单独统计,六百多万个像素清一色是 0,这是 BC5 法线最铁的指纹。那么问题来了:地表的颜色从哪来?
答案是——没有颜色贴图。地表颜色完全靠程序上色。 那个写死的 dirt_color(泥土 RGB)+ grading(昼夜调色),就是地表颜色的全部来源。着色器拿法线做光影,拿 dirt_color 定基调,拿 grading 调时段氛围,颜色是「算」上去的,不是「贴」上去的。
我把这个发现验证到了全部 15 张地表材质——清一色都是 BC5 法线数组,没有一张 albedo(颜色)贴图。 而且它们的层数还不一样:forest 是 26 层,desert 是 30 层,arctic 是 29 层……每一层是一种地表细节的法线变体,着色器按地表类型 / 坡度索引不同的层,混出「低处草、高处岩、坡上土」的过渡。

再看 dirt_color,有个只有把数据摊开才看得见的规律:它只有 3 种取值。
| 底色 | RGB | 覆盖群系 |
|---|---|---|
| 雪白 | [1, 1, 1] | 极地、雪林(2 个) |
| 暖褐 | [.17, .11, .06] | 沙漠、沙地、草原、岩石、熔岩、虫巢、绿洲(7 个) |
| 林绿 | [.15, .14, .06] | 森林、针叶、落叶、荒原、原始、沼泽、超级地球(7 个) |
16 个群系的地表色,本质是 3 种底色的复用。 从冰原到沼泽到熔岩的全部地表色调,就靠这 3 个写死的 RGB + 每群系独立的昼夜 grading 调出来。有限的几个数值 + 程序上色,撑起了所有星球的地表。

本次检查的材质使用法线资源和颜色参数共同构成地表外观。BC5 保存两个通道,第三个法线分量可在 Shader 中重建;这份资源的格式不能证明整个地形只使用一张纹理,也不能证明所有凹凸细节都无法计算。
六、这堵墙:能还原规则,还原不了那一次
讲到这里,这套地形系统的能力和边界都露出来了。
已经确认的是区域、子区域、Voronoi 拓扑和支撑形状等静态结构,以及本文所检查材质资源的格式。它们的实际执行顺序和混合函数,需要运行时证据;静态类型不能替代完整算法。
当时尚未取得具体请求的完整选择、布局和高度计算路径。这里描述的是研究进度,不是对数据永久不可恢复的判断。
当时记录的文件熵约为 7.99/8.0,说明字节分布接近均匀。仅凭高熵、缺少可识别头部或附加字段,不能确定认证加密、每文件不同密钥或无法静态恢复;这些判断需要格式或处理代码的直接证据。
所以当时的恢复边界是清晰的:能还原到「规则 + 结构」的粒度,还原不了「那一次具体装配的种子与编排」。 能说清「这类星球用这套规则生成地形」,说不清「这颗星球这次长成的精确样子」。
地形与物件都需要区分静态资源关系和本局实例生成。当时未恢复完整布局,后续则已经验证固定请求的地点与自然 Stamp 分支。因此应把边界写成某个日期、某个分支的研究状态。
七、在 UE5 里还原的思路
第六章那堵墙,挡住的是「那一次的种子与编排」,没有挡住「规则」。而规则一旦在手,便自然引出下一个问题:这套规则,是否足以支撑我们在引擎中自行生成一片地? 答案是肯定的——本节讲清落地的思路,具体的代码、调参与最终效果另立一篇详述,这里聚焦于「为什么是这条路径」。
出发点:地形不是存下来的,是算出来的
当时未找到可直接导入的完整最终高度图。这个结果不能排除局部静态高度资产:后续已经确认自然 Stamp 与 Location 高度纹理参与生成。还原工作需要追踪配置、实例与高度计算,不能只寻找一张完整成品图。
下面的三层表达式是当时用于试验的代理模型,用来组织基底、表面变化和局部修改;它不是已恢复的原版完整公式。
Height(x, y) = Stamp( Displacement( VoronoiBase(x, y) ) )
将原型写成高度查询接口,便于测试和移植。接口形式本身并不证明每个阶段只依赖坐标与 Seed,也不证明可以任意并行。

本地重建能够减少完整高度场的常规传输,但需要相同算法版本、配置、资产和数值规则。服务器仍要发送会话与布局信息,并检查摘要;不一致时可能需要补发地形块。不能称为只传 Seed 或零地形带宽。
三层,正好是前面逆出来的三样零件
以下三层是早期工程原型的职责划分,不是原版调用顺序。
基底层用于研究区域尺度的起伏。当时试验过 Voronoi 台地及边界曲线,后来不再把这一方案写成原版已确认算法。现有还原应按实际的来源赋高、角点权重、栅格化和平滑解释。
表面变化层在代理模型中补充局部起伏。噪声振幅如何选择,是该原型的参数问题;不能仅因存在 Displacement 类型,就断言原版必然在六级平台上叠加噪声。

局部修改层按原型规则调整地点和道路附近的地面。自然 Stamp、地点支撑、地点高度纹理与道路修形需要区分职责,不能把它们全部归成最终一次压平。
修改顺序会影响结果,必须以实际阶段记录为准;下面的示意只说明后续修改可能改变已有地面。
这三层曾用于验证代理模型的实现和接口。后续恢复出的高度生成链更细,不能用早期模型替代其真实阶段顺序。
引擎侧:每一环都有 UE5 的原生机制接着
思路厘清后,落到 UE5 上,材质一环几乎无需额外开发,但几何一环——「运行时把地算出来」——恰恰是整个方案中最困难的部分,也最容易被一句「用 World Partition 流送即可」敷衍带过。 先讲透这块最关键的,再说相对简单的材质。
高度计算、网格提交与碰撞创建需要分别安排。后台任务可以降低游戏线程等待,但分块并行的前提是共享输入已准备好,邻域滤波和布局依赖得到处理,提交顺序可控。玩家入场还要等待必要地形与碰撞就绪;本文没有证明任意分块都零依赖或保证完全不卡顿。
难点二:World Partition 能提供帮助,但帮的不是通常设想的那一半。 此处需澄清一个容易想当然的误区。World Partition 的职责是「玩家行至何处,便将该区域磁盘上已存在的关卡内容加载进来」——注意「已存在」三字:它搬运的是烘好、存盘的内容,其本身不会「现场生成」一块地。因此指望「将地形交给 WP,它便顺带将地形也流送了」是不可行的,因为我们的地形在开图前并不存在于任何磁盘包中,需要现场计算。
那么 WP 如何使用?用它的触发信号,而非它的搬运能力。WP 提供一个可自行实现、自行注册的「加载源」接口(IWorldPartitionStreamingSourceProvider / RegisterStreamingSourceProvider)——玩家角色即是一个加载源,持续告知系统「我位于此坐标、此朝向」。我们的做法,是复用这同一加载源的位置信号,驱动自己的地形烘焙调度:玩家移动到何处,即以其为圆心,令附近应出现的地块进入后台烘焙队列,已远离的地块卸载网格以释放内存。最终形成两套机制并行运转、由同一位置信号统一指挥的结构——WP 负责流送地面上已制作好的物件(建筑、货箱、植被),我们的调度器负责按需现算脚下的地。将「WP 流送已有内容」与「我们现算地形」二者厘清,是本方案在引擎侧不出错的关键,也是「用 World Partition 即可」这句话的真正含义。

LOD 需要单独处理边界。相同高度函数可以供不同密度的网格采样,但粗细网格的边界细分不同,仍可能出现 T 形连接和裂缝。共享边采样、边界重建或裙边需要明确设计和验证。
几何部分讲完,材质一环确实无需额外开发,因为第五章逆向出的结构与 UE 的材质体系天然同构。原作「一张 BC5 法线数组 + dirt_color 底色 + 昼夜 grading」的做法,对应到 UE 即「一张 Texture2DArray + 一张母材质 + 每个群系一个材质实例」:法线数组提供凹凸细节,底色与调色均作为材质参数。原作 16 个群系复用 3 种底色,在 UE 中即 16 个实例共享一张母材质、仅改参数——这套复用结构无需重新设计,可直接沿用。
本文检查的法线资源包含 BC5 双通道、26 层数组和多级 mip。保留 DDS 等支持数组和 mip 的格式,便于保存原结构;PNG 可以保存线性通道或单层预览,但单个普通 PNG 不能承载这份完整资源。导入时仍需正确设置线性采样、数组层和法线重建。
到这里为止,与再往上的层
需要说清本节的边界:以上讲的是地形的几何与地表材质——把一片有起伏、有材质的地算出来、生成出来。但一片真正可玩的地,之上还有几层本节未展开、将在后续文章补齐:
- 光照(Lighting):地表法线只解决了「凹凸细节」,真正的明暗要靠光照系统——直接光、天光、阴影,以及原作那套按昼夜三档 grading 调色的时段氛围如何在 UE 中落地(Color Grading LUT + 后处理),是单独一层。
- 玩法层(Gameplay):地形不只是背景,它要参与玩法——AI 寻路要读地形高度、掩体与视线判定要吃地形起伏、印章压出的降落区/据点要与任务系统对接。这一层是「地形数据如何被 Gameplay 使用」。
- 网格与碰撞有不同的创建和提交流程。玩家进入某块地形之前,必须确认所需碰撞可用;这不要求两种资源一定在同一帧创建。异步完成后的状态检查与入场条件需要单独实现。
本节聚焦几何与材质这一最基础的层;光照、玩法、物理如何在其上叠加,各自都值得单独展开。
收束
一句话概括这套落地思路:将逆向出的规则实现为一个「计算高度」的函数,三层自内向外——离散平台提供骨架、噪声提供肌理、印章提供可控内容;将该函数切分为一块块、后台并行烘焙、由玩家位置驱动按需生成与卸载;材质沿用逆向出的法线数组 + 程序上色。 其中最需投入的是运行时烘焙一环——厘清「引擎流送已有物件」与「我们现算脚下地形」这两条并行的线;而材质一环几乎可直接沿用。至于这个函数具体如何实现、崖壁曲线如何调节、后台烘焙的性能是否可承受、最终效果与原作是否接近,都值得单开一篇以实测与截图说明,这里先行收束。
回到本篇:引擎中的地形至此便有了着落,不再是「正确但光秃」的灰色网格,而是一片换一个种子即重新生成、有平台有陡坡有材质的地——再由下篇的填充系统在其上铺设植被、放置建筑,一颗星球才真正立起来。
八、总结:这一篇在整条装配线里的位置
把这一篇收成一句话:它讲的是「地怎么长出来」——切块、定高、盖印章、上色,全靠规则和种子算,不靠手工雕、不靠贴图堆。
这套「规则 + 库存 + 种子」的思路,会一路贯穿到下篇:
- 本篇整理区域结构、几何类型、样本地形与法线材质,并记录当时的工程原型思路。
- 下篇([两套填充系统])——用同一套思路填充物:按群系铺植被、按阵营拼建筑。
地形和填充共同参与场景构建;这两篇记录的是早期结构分析与原型方案,不构成完整星球生成算法的验收。
对想做开放世界的人,可迁移的不是「这游戏地形长什么样」,而是这套地形装配思路:
- 地形不必手工雕,可以是「Voronoi 切块 + 离散高度 + 印章 + 程序上色」的现算;
- 随机和可控可以并存——随机的地形底,加确定性的印章(基地、道路),既每局不同又关键地形可控;
- 地表不必堆一堆贴图,可以「只存法线、颜色靠程序调」,把存储压到极致,还能一套底色复用到几十个群系。
理解了这套思路,就理解了这类游戏怎么用极少的数据,算出一整颗看不到边的星球。 星球再多,也只是同一套规则库的重新装配——地是这么来的,下篇会讲,地上的东西也是这么填的。
九、AI 协作复盘
这是本系列的固定栏目:记录做这一篇时,人和 AI 具体怎么配合、哪里翻了车、人怎么补的位。
AI 帮上忙的地方:
- 「地表实为法线而非颜色」是核对格式得出的。最初将那张贴图当作地表颜色图(其假色与绿草黄土极为相似),是在核对它的真实压缩格式(BC5)、数组层数(26)、通道分布(蓝通道六百万像素恒为 0)时,才推出「这是法线贴图、地表根本没有颜色贴图」这一结论。AI 在「将二进制格式逐字段拆解核对」上表现稳定,能用数据推翻肉眼的误判。
- 类型核查应说明看到了什么,也要说明没有覆盖哪些资源层级。20 个类型未出现贴图字段,不能推出整个高度管线零纹理输入。
- 地形块尺寸、顶点密度、42% 起伏分类和 dirt_color 档位来自当时样本统计。保留这些测量时,需要把样本特征与运行时算法解释分开。
失误与人的补位:
- 「地表材质无法提取」曾是一个误判。中途一次提取地表材质直接崩溃(撞上一个损坏的游戏数据包),我一度得出「地表材质实体无法提取、只有引用 ID」的结论,还险些将其归入「加密无法获取」一栏。是换用一个能绕过坏包的提取器版本,才发现材质实际可以提取——此前的「无法提取」是被环境问题误导的错误结论。AI 有「一次失败即下定论」的倾向,人在回路中追问「是真的无法获取,还是工具的问题」,才避免了这一错误结论遗留。
- 导出格式需要保留资源本来的通道、数组层和 mip。单个普通 PNG 适合查看某一层,但无法保留完整数组与 mip 链;DDS 等格式可以承载这类结构。错误来源是丢失结构或导入设置不匹配,不能笼统地说 PNG 必然丢通道或编码错误。
- 中文文件名被人纠正。产出文档时我使用了中文文件名,人明确要求「文件不得使用中文」——中文路径跨工具易出编码问题,也不够规范。当即全部改为英文并同步所有引用。约定性的规范,人确立一次,AI 需记住并回头修正已犯的部分。
检查压缩格式、数组层数与通道分布,纠正了把本次法线资源当作颜色贴图的误读。这个结论只覆盖所检查的资源,不能据此排除其他材质或其他阶段的颜色纹理。
配图为结构说明或早期原型示意。1243 个地形块的测量、16 个群系和材质格式沿用历史记录;生成算法的解释以修订后的证据边界为准。本文不再由类型字段缺失推断零纹理输入,也不再将六档台阶或数据加密当作已证实结论。