
简介一份面向CityEngine初学者的入门笔记PDF系统梳理ESRI公司基于CGA语句的程序化建模思路将建筑高度、层高、窗宽、纹理等参数以代码方式定义支撑大规模批量建模。内容涵盖属性定义、句柄调整、模型构建、常数定义、随机纹理五个核心模块并配有CGA语法示例适合城市规划、游戏场景、电影模型等领域的建模人员快速上手。资源为单个PDF文档压缩包仅1.42MB轻量便携可随时翻阅。目前已有949人学习下载。笔记从Group分组属性、Range取值限制、Handle句柄交互到comp/split等面分割规则均有介绍示例由简单建筑体块逐步递进至立面分割配合注释讲解各属性、函数与常量的作用读者可借此理解CE参数化建模流程减少从官方文档入门的摸索成本快速构建可调节的建筑原型。1. CityEngine 入门卡在哪一步才最值得死磕见面先说结论cityengine 入门 的核心不是学会点按钮而是学会读和写 CGA 规则。第一次打开这个软件的人十有八九会迷失在三维视口和一堆选项卡里翻半天菜单也做不出一栋像样的楼反过来只要理解了一条“地块→挤高→切面→对面做开窗”的规则递推后面几十栋楼、整个街区都是同一套逻辑的批量复制。这篇笔记从界面识别、数据导入、CGA 语法到踩坑排查按我处理真实项目的顺序把完整路径写出来。适合拿到的是一堆 Shapefile 和卫星底图、要做规划方案或游戏场景原型、却被手工建模折磨到想放弃的人。2. 环境与界面盘清把第一块 Shapefile 变成一座建筑CityEngine 桌面版给人的第一印象是“视图真多”。它不像 Blender 那样只有一个主视口加一堆面板而是把规则编辑、场景图层、属性检查和三维预览拆成了好几个窗口。新手最容易犯的错是先去研究每个按钮干什么结果一晚上过去还在视口里转镜头。我一般建议只先认识四个地方三维视口、图层窗口、CGA 编辑器、属性检查器。围着这四个窗口走通一遍流程再回头看不认识的按钮也不迟。2.1 先认识四个窗口场景、图层、CGA 编辑器与检查器三维视口在正中央负责显示地形、地块和生成后的模型鼠标左键旋转、中键平移、滚轮缩放这个操作跟大多数 DCC 软件一致。左下方或独立停靠的图层窗口列出当前场景里的所有图层比如地形图层、地块图层、道路图层每个图层前面有一个小眼睛控制显隐。CGA 编辑器在底部或侧边是一个纯文本编辑区写规则、保存规则都在这里语法错误会直接显示在它下方的消息区。属性检查器通常在右侧选中任意一个地块后它会列出这个地块的属性包括来自数据源的字段和规则里定义的属性。属性检查器在入门阶段容易被忽略但它恰恰是调参最爽的地方你在 CGA 里写好attr floorCount 10保存并应用后右侧会出现一个数字输入框把 10 改成 20模型立刻重新生成。这个“写规则→拖动参数→实时看结果”的循环就是 CityEngine 和普通建模软件最本质的差别。我把这个循环称为规则驱动的工作流。2.2 导入 Shapefile坐标系、单位和字段名决定了第一印象拿到一份地块数据后最常见的操作是File → Import → Shapefile。这个导入过程看起来简单但有一件事必须在导入前确认.prj文件是否存在。.prj记录了数据的坐标系缺失时 CityEngine 会弹一个对话框让你选择坐标系。这里的典型错误是随手选一个或者选成经纬度坐标系的 WGS84结果导入后地块跑到几公里外。我一般会在导入前用 QGIS 打开 Shapefile在图层属性里看坐标系和单位如果是经纬度就先投影成 Web Mercator 或当地高斯投影再导出一次。单位不一致是另一个大坑。有些数据虽然坐标系正确但几何单位是英尺或不知道什么单位导入后地块尺寸和地形比例对不上。判断方法很简单导入后选一块已知边长的地块在检查器里看它的尺寸是多少。如果一块真实宽度为 30 米的地块显示成 3000说明数据单位是厘米级偏差需要利用软件里的单位换算或重新投影。字段名也值得提前检查因为后面规则里要直接用字段比如地块高度字段叫height还是H楼层数字段叫floors还是FL规则里写错了名字生成时不会报错只会按默认值执行这种静默失败最难受。小区块测试是个好习惯。我拿到任何数据会先在图层上删到只剩三五块地导入测试跑通后再把完整数据替换进去。这样做的理由是完整数据动辄上千个面一旦出现规则错误或者数据拓扑问题很难判断到底是规则写错还是数据源有问题只留三块地所有变量肉眼可见。CityEngine 有撤销功能但规则生成的结果在部分版本里撤销并不彻底小范围测试是最稳妥的后悔药。3. CGA 规则语法形状是怎么被一层层推出来的CGA 是 CityEngine 的规则语言全称 Computer Generated Architecture。它和 Python、JavaScript 这类通用语言完全不同不写循环、不定义函数返回值而是用“形状替换”来表达逻辑一个形状被规则匹配后被替换成若干个新形状新形状再被下一条规则匹配层层递推直到所有形状都被处理成最终模型。理解不了这个递推模型后面写规则很容易卡住。3.1 规则的基本结构形状、规则名与替换一份 CGA 文件是一个纯文本文件后缀通常为.cga。文件里每条规则的基本形式是“左侧一个形状名冒号右侧一串操作”。例如下面这段代码是完整的入门级规则StartRule Lot -- extrude(world.y, 10) Mass Mass -- comp(f) { front : Facade top : Roof side : Facade }第一行StartRule是入口标记它告诉 CityEngine 规则从这里开始执行。Lot是输入形状的默认名称也可以改成地块图层的名字。第二行extrude(world.y, 10)把当前形状沿世界 Y 轴拉伸 10 米生成一个体块随后这个体块进入名为Mass的规则。在Mass里comp(f)把体块按面拆分为前面、顶面、侧面三部分各自进入新的规则处理。这条规则背后的思想是把一个复杂建筑拆成“整体→面→局部面”的层级每层只管一层事。这里要特别说明StartRule的重要性。如果规则文件里没有这一行选中地块后点击应用规则软件可能毫无反应也不给任何提示。这是个非常容易劝退新手的点。一个规则文件里可以只写一个入口也可以写多个但选用的规则文件必须保证入口存在。我把这个入口视为所有地块的“大门”没有大门建筑永远生成不出来。3.2 三大核心操作extrude、comp 与 splitextrude的作用是拉伸。常见写法是extrude(world.y, 高度)表示沿世界坐标 Y 轴方向拉伸指定高度。也可以传入数值表达式比如extrude(world.y, height)这里的height可以是规则里定义的属性也可以是 Shapefile 里的字段。当数据源有高度字段时这个写法就是“批量生成不同高度建筑”的关键。需要提醒的是extrude生成的是封闭体块顶面和底面也会被创建如果不处理它们后续贴图阶段会出现底面也贴墙面材质的情况。comp的作用是拆分。comp(f)表示按面拆分f是 face 的缩写。括号里的大括号内是分面规则标准用法如front : Facade、top : Roof、side : Wall冒号左边是面方向右边是下一步要进入的规则。除了f还有e表示按边拆分、v表示按顶点拆分入门阶段用到最多的是f。需要注意方向关键字front、back、left、right、top、bottom是基于形状局部坐标系的不是世界坐标如果一个地块旋转过front可能朝东也可能朝南出问题时不要怀疑规则写错先看形状的局部坐标系方向。split的作用是切割。这是做立面最常用的操作常见写法是split(y) { ~3 : Floor }*意思是沿局部 Y 方向切割每层高约 3 米*代表重复切割直到剩余高度不足为止。波浪号~表示“近似分配”软件会根据实际总高度自动微调每一段的尺寸避免最后一段高度和其他层差太多。如果想要等宽切割可以写成split(x) { 2 : A | 1 : B }竖线是分隔符按从左到右的顺序依次切出 2 米宽的 A 段和 1 米宽的 B 段然后再循环通常要配合*使用。3.3 用参数和随机数控制立面attr 与 case写死高度的规则只能应付固定场景。实际项目里楼层数、层高、窗户宽度、屋顶形式每一项都可能变。CGA 的属性机制把它解成了“规则文件 参数”两层version 2024.0 Group(建筑控制) Range(3, 40) attr floorCount 10 Group(建筑控制) Range(2.5, 4.5) attr floorHeight 3.2 StartRule Lot -- extrude(world.y, floorCount * floorHeight) comp(f) { front : Facade top : Roof }Group让属性在检查器里归到名为“建筑控制”的分组下Range(3, 40)定义滑块的最小值和最大值。保存规则、应用规则后检查器里会出现这两个属性拖动滑块就能改变楼高和层高。这种方式比改代码高效得多尤其在给客户或非技术同事展示方案时一个滑块就能解释“为什么楼高能调”。随机化是 CGA 另一项利器。case关键字可以根据条件选择不同分支Window -- case random() 0.4 : set(material.colortex, assets/textures/curtain_a.png) else : set(material.colortex, assets/textures/window_b.png)random()返回 0 到 1 之间的随机数配合case可以让每扇窗户有 40% 的概率用 A 贴图60% 用 B 贴图。这种随机性在远距离看街区时特别重要否则一整条街的窗户纹理完全相同一眼看去非常假。随机数不是每次点击都变化的它与形状的种子值相关想固定随机结果时不要动地块形状顺序想换一批随机结果时选中生成后的模型重置再生成即可。4. 从地块到街区一条能落地的入门建模流程前面三章理解了这一章是完整的“抄作业”流程。我会把一个街区生成过程拆成三步准备数据、写规则、调参出图。每一步完成什么、失败看哪里都写清楚。4.1 准备地块数据把图层清理到能导入的状态最常见的做法是从 OpenStreetMap 或规划部门拿到地块边界然后再做三步清理。第一步目视检查有没有重复面、重叠面、自相交。CityEngine 对重叠面很敏感两块地重叠会导致生成结果互相穿插。第二步检查地块边界是否闭合。Shapefile 在转换过程中偶尔会出现边界不闭合的情况这种面在 CityEngine 里表现为生成楼体时侧面缺一块。第三步确认地块面方向。面有正反之分法线朝下的面会让楼体往地下长。这个可以用 QGIS 的“修复几何”工具批量处理也可以在 CityEngine 里选中地块后右键检查法线方向。地形数据也要提前确认坐标系和范围。常见流程是导入地形 TIF 或 DEM 栅格然后通过Layer → Create Terrain生成地形模型。需要注意地形的单位必须和地块一致否则地块要么悬浮在空中要么埋进地里。我的习惯是地形作为底图地块作为生成层两者分开管理别把地块自动落在地形上否则后续调地块高度时会被地形高度干扰。4.2 写一份中等复杂的街区规则并应用下面这份规则比入门版复杂一些它能完成“沿街立面、顶层收口、开窗”三个动作你可以在 CGA 编辑器里直接粘贴运行version 2024.0 Group(楼层) Range(2, 30) attr floorCount 8 Group(楼层) Range(2.5, 5.0) attr floorHeight 3.2 Group(立面) Range(2, 6) attr windowWidth 3.0 StartRule Lot -- extrude(world.y, floorCount * floorHeight) comp(f) { front : Facade top : Roof side : Facade bottom: NIL } Facade -- setupProjection(0, scope.xy, 4, 3.2) set(material.colortex, assets/textures/wall_brick.png) color(#c8b090) split(y) { { ~floorHeight : Floor }* } Floor -- split(x) { { ~windowWidth : WindowTile | 0.4 : Pillar }* } WindowTile -- case random() 0.7 : set(material.colortex, assets/textures/window.png) else : set(material.colortex, assets/textures/wall_brick.png) s(3.6, 2.8, 0.4) t(0, 0.15, 0.1) Pillar -- set(material.colortex, assets/textures/pillar.png) Roof -- color(#5a5a5a)逐段说明一下。最开始的几个attr定义了楼层数、层高和窗宽这是后面所有计算的公共参数。Lot规则先把地块拉伸成体块再用comp(f)拆分六个面。注意我写了bottom: NIL这是常用的写法表示底面直接丢弃不生成任何几何体否则底面会在渲染时和地形重叠产生黑暗色块。Facade规则先用setupProjection(0, scope.xy, 4, 3.2)设置 UV 投影方式按局部平面投影贴图尺寸为 4 米乘 3.2 米这是为了控制砖墙纹理的重复密度。set(material.colortex, ...)是给当前形状指定纹理color(#c8b090)是整体着色相当于给模型一个淡黄褐色基调。然后split(y)按层高切出每一层并交给Floor规则。Floor规则按窗宽切分每段约windowWidth米宽中间夹 0.4 米宽的柱。WindowTile里用random()决定这块区域是窗户还是实墙然后再横向缩放并偏移做出窗台厚度。最后Roof只是简单给了个深灰色。这份规则跑通后你会看到一排有窗、有柱、有颜色的建筑排在一起视觉上已经接近规划方案的效果图底稿。应用规则时在场景中选中所有地块然后在 CGA 编辑器工具栏点“应用规则文件”或者直接右键选中面选择应用规则。规则应用完成后视口里立刻生成大量模型如果模型没出现回到 CGA 编辑器的消息区看日志最常见的错误是extrude参数传入了字符串而非数字。日志里一般会给出具体行号双击错误行可以直接跳到对应位置。4.3 调参出图检查器里的滑块就是后悔药规则应用成功后右侧检查器会列出floorCount、floorHeight、windowWidth三个滑块。把floorCount从 8 拖到 16整条街的楼层数立刻翻倍把windowWidth拖到 5窗户变宽柱子间距变大。这种实时反馈就是 CityEngine 最值得付出的学习成本。需要注意属性修改后只要没有保存规则文件滑块调整的结果是临时的。一旦保存规则文件下一次重新应用时滑块值会被规则文件里的默认值覆盖。想保留调好的参数建议规则文件里使用默认值然后依赖检查器里的属性来做方案比选不要混着改避免“为什么保存后又变回去了”的困惑。这个坑我踩过不止一次后来养成的习惯是在规则文件里固定最合理的默认值项目参数全部通过检查器调整一切有迹可循。5. CityEngine 避坑排查五个真实翻车现场与解法规则写多了翻车是家常便饭。有些问题报错明确有些完全沉默沉默的最可怕。下面这五条都是项目里反复遇到过的按“现象、原因、解决”拆开写你遇到时可以直接对照。5.1 应用规则后什么都没生成也不报错这是最常见的入门级故障。选中地块、点击应用规则视口毫无变化日志窗口一清二白。排查顺序是这样先确认规则文件里有没有StartRule入口没有入口规则无法启动这是 60% 的情况。再看地块图层是否被隐藏或者锁定了图层隐藏时规则能应用但视口不显示看起来就像没生成。最后检查是否选中的应用规则文件是对的文件名和路径都不要有中文或空格某些版本对中文路径支持不佳规则文件读不出来。5.2 建筑只有一侧有窗户其他面全是实墙现象是挤出的建筑体块只有某个朝向有窗有门其他立面空荡荡。原因在于comp(f)的面方向判定。front是形状局部坐标的前方向如果地块旋转了 90 度front就不再是街道朝向。解决方法是先确认地块的局部坐标系选中地块观察视口里的方向指示如果有必要可以将规则里的方向改为多个方向映射到同一个立面规则比如front : Facade | right : Facade | left : Facade | back : Facade这样无论地块怎么转四个方向都有完整立面。5.3 楼体穿地或者浮空楼体穿地的典型场景是地形有起伏但地块是平面地块上的建筑按海平面标高生成结果遇到上坡路面被埋住。原因有两个层次一是地形和地块数据本身的坐标系不一致二是地块没有真的贴在地形上。解决方法是先检查两者坐标系如果一致再在 CityEngine 里把地块图层和地形图层对齐常见做法是打开地块图层的“对齐到表面”选项让地块面整体贴在地形表面上。另一个经验是少量穿地不必太较真只要建筑一层地面线和道路衔接不是太离谱最终效果图看不出来如果穿得厉害直接抬高地块或调整地形数值即可别让问题延后到导出阶段才暴露。5.4 split 规则只切出第一层后面不执行在split(y) { ~floorHeight : Floor }*这种写法里很多人会漏掉末尾的*结果只生成了第一层楼板整栋楼只有一层。原理是缺少*时split 按从左到右执行一次就结束加上*才会循环切分直到高度余量不足。这个报错不一定出现属于沉默型故障。另一个相似问题是用|分隔多个切割段时顺序写错导致后续段永远不触发。解决方法是把切割顺序从头到尾读一遍从左到右依次切*表示重复~表示近似分配三者配合时先手算一小段验证逻辑不要直接在大场景上跑。5.5 导出到其他软件后纹理丢失或发黑CityEngine 里看起来正常导出成 FBX 或 OBJ 后在其他软件里打开模型在但纹理全黑或缺失。原因是纹理贴图路径没有被正确传递。CityEngine 默认用绝对路径引用贴图比如assets/textures/wall.png在导出时被写作C:/Users/xxx/project/assets/textures/wall.png换一台机器或移动项目目录后就找不到文件。解决方式是把项目整体打包成.rpk规则包或者导出时勾选“嵌入纹理”选项让贴图跟随 FBX 文件走。另一种稳妥做法是导出前把所有贴图复制到项目根目录下的assets/textures文件夹并保证规则里用的是相对路径。这个坑往往在交接文件时爆发合作方收到模型打开全黑免不了又要解释一轮。6. 进阶收尾把规则库和纹理下载沉淀成自己的资产包走到这一步你已经能用 CGA 规则批量生成一条街了。下一个值得投入的方向是建立自己的 cityengine 规则库。我现在的习惯是每个项目结束后把那些可复用的规则抽出来统一结构放到一个固定目录里比如rules/common/、rules/residential/、rules/commercial/同时把用得到的重复贴图整理到assets/textures/下按砖墙、玻璃、屋顶、百叶窗分类。这样下次新项目只要拷贝规则库和纹理库写新规则时只需引用现成资产效率能提升一大截。纹理下载一直是很多人卡住的点。刚开始我会去各类免费纹理站下载整包贴图但很快发现不同来源的贴图画风和分辨率参差不齐用在同一个项目里会显得很突兀。后来我定了一条原则一个项目只用一到两个来源的纹理并且优先下载无缝拼贴seamless版本因为 CGA 立面几乎全靠 UV 平铺普通纹理一旦平铺就会露馅。下载时还要注意看许可证路径不要带中文贴图尺寸统一压到 1024 或 2048这对导出体积和视口预览都有帮助。最后分享一个验证规则库是否成熟的小技巧在小场景里放置三种不同形状的地块一种狭长、一种方正、一种带斜边然后把你的通用规则应用上去。如果三种地块上生成的建筑都没有穿帮——窗户尺寸合理、屋顶没有悬空、墙角没有裂缝——这个规则才算“出门可用”。我会定期把这样的测试场景存成一个底座文件任何新规则都先在底座上跑一遍而不是直接放到大项目里碰运气。这个习惯帮我省掉了大量返工也希望帮到你。本文还有配套的精品资源点击获取