简介:Cesium for Unity 1.9版本包文件是一套面向Unity引擎的三维地球可视化扩展工具,可让开发者直接在Unity中使用Cesium的高精度卫星影像与地形数据,用于构建仿真、游戏、地图服务或教学演示项目。压缩包共482个文件,主要有133个C#脚本、跨平台原生库(.a/.dll/.so)、着色器、材质、纹理图片与说明文档,并附带Unity资源导入所需的meta配置,整体约194MB。已有619人学习下载。1.9版本重点优化大数据量地形加载与渲染性能,扩展了API以支持光照阴影控制、时间动态播放和KML数据导入,便于展示地理标记与轨迹。包内还包含Cesium World Terrain、Cesium Clock等核心组件、package.json管理器配置和第三方依赖说明,导入后即可快速搭建三维地球场景,再通过自定义脚本控制图层、相机与交互逻辑,可大幅缩短地理空间项目的开发周期,适合中高级Unity开发者学习使用。
1. 拿到 Cesium for Unity 1.9 包文件,先别急着往 Assets 里拖
下载过 Cesium for Unity 1.9 包文件的同学,十有八九干过这件事:把解压出来的文件夹直接拖进 Unity 的 Assets 目录,然后等编辑器重启,等来的是一屏编译报错。原因很简单——Cesium for Unity 1.9 不是传统意义的 Asset Store 资源包,它是按 Unity Package Manager(UPM)规范打包的 .tgz 包,该进 Packages 而不是 Assets。这个版本解决的是全球 3D Tiles 流式加载、Cesium World Terrain 地形与影像叠加这类 GIS 场景,适合做数字孪生底座、航测数据展示和城市级可视化的 Unity 团队。如果你手头已经有一份 .tgz,或从 GitHub Releases 找到了对应 tag,这篇笔记带你把它正确装进工程、跑通最小场景,并把 1.9 最坑的几处参数一次说透。
2. 确认包文件形态与安装方式:为什么 tgz 不能进 Assets
2.1 三种包文件形态:tgz、内嵌包与源码包
Cesium for Unity 1.9 在安装前,先要辨清你手里的“包文件”是哪种形态。最常见的发布形态是.tgz,这是 UPM 的标准压缩包,里面带package.json清单、Runtime 程序集、Editor 工具脚本和 native plugin;第二种是已经内嵌在 Unity 工程 Packages 缓存里的形式,你通过 UPM 的 git URL 或 OpenUPM 安装过,之后在Packages/manifest.json里能看到com.cesium.unity一行;第三种是 GitHub 仓库源码,拉下来后需要自己把com.cesium.unity子目录链接到工程里,适合想看实现的人。
不论哪种形态,Cesium for Unity 1.9 都不是一个“把文件夹往 Assets 一丢就能跑”的普通资源。它的 native 插件层是预编译好的动态库,UPM 安装时 Unity 会在导入阶段完成 dll/so 的识别与平台校验,而 Assets 目录下的脚本无法享受这套依赖解析,结果就是你看到的那一堆CS0246找不到程序集的报错。
2.2 用 UPM 离线安装:Add package from tarball 的完整步骤
我一般会把手里的 1.9 tgz 放在工程目录之外,比如D:/cesium-packages/,避免 Unity 把包文件本身当作内容反复扫描。接下来有两种装法,推荐第一种。
先打开 Package Manager:
- 菜单栏
Window > Package Manager - 左上角
+按钮,选Add package from tarball... - 选中
com.cesium.unity-1.9.0.tgz - 等待右下角解析完成,过程可能要 1 到 3 分钟,取决于机器磁盘速度
如果编辑器长期停在“解析中”,用第二种方法,直接改 manifest.json:
手动编辑工程根目录下的Packages/manifest.json,在dependencies里加一行:
{ "dependencies": { "com.cesium.unity": "file:D:/cesium-packages/com.cesium.unity-1.9.0.tgz", "com.unity.mathematics": "1.2.1", "com.unity.collections": "1.2.4" } }路径里file:后接绝对路径最稳,相对路径在换机器后容易失效。manifest.json 里如果缺com.unity.mathematics这类依赖,UPM 会自动从官方 registry 补拉,网络不好时会卡很久,所以离线下建议先把这几个依赖版本也写上。
装完后验证一下,打开Packages/com.cesium.unity,至少能看到Runtime、Editor、Plugins三个目录。也可以直接用命令行确认 tgz 内容没有损坏:
tar -tzf com.cesium.unity-1.9.0.tgz | head -n 20正常输出里第一个文件应该是package/package.json。如果第一条就是乱码路径或package/缺失,那这个包大概率不是标准 UPM 包,装进去必然报 invalid。
2.3 装完后看清包结构:Runtime、Editor、Plugins 各自做什么
包结构决定了你后续排错的方向。1.9 里Runtime放的是CesiumForUnity.Runtime.dll与 C# 脚本,包含CesiumGeoreference、Cesium3DTileset、CesiumGlobeAnchor这些组件的运行时逻辑;Editor目录只有编辑器阶段才会编译,Unity 菜单栏里的Cesium菜单都从这里来;Plugins是 cesium-native 的绑定层,也就是真正干加载 3D Tiles、解析 glTF、调度瓦片请求的动态库。
理解这套结构后,遇到“编辑器正常但打包后没有地形”这类问题,你不会再去反复改代码,而是先检查 Plugins 是否被正确包含在 Build 平台里。1.9 对 Windows、Linux、macOS 分别发布了对应动态库,不要只拷一个 dll 到 Assets 就指望 Android 能跑,Cesium for Unity 1.9 对移动端的支持相当有限,这点后面避坑章节会提到。
3. 跑通最小场景:Georeference 与 World Terrain 三件套
3.1 先配 CesiumIon Token,再创建地形三件套
打开一个空场景,菜单栏选Cesium > Create > Cesium Georeference,场景里会出现一个空的CesiumGeoreference对象。它是整个工程的“世界原点”,决定 Unity 坐标原点对应地球上的哪个经纬度。紧接着用Cesium > Create > Cesium World Terrain创建地形,它会自动挂在 Georeference 下面,场景里会出现Cesium3DTileset和CesiumRasterOverlay两个组件。
这三件套里,CesiumGeoreference管坐标换算,Cesium3DTileset管地形网格加载,CesiumRasterOverlay管影像贴图。1.9 里默认加载的是 Cesium World Terrain 和 Bing 影像,这两个服务都需要 Cesium ion 的 token。把 token 填到CesiumIonServer组件的Default Token字段,或者用脚本在启动时设置:
using CesiumForUnity; using UnityEngine; public class SetupCesiumToken : MonoBehaviour { public string ionToken = "你的_ion_token"; void Start() { CesiumIonServer server = FindObjectOfType<CesiumIonServer>(); if (server != null) { server.DefaultToken = ionToken; server.DefaultTokenAuthoring = ionToken; } Debug.Log("Cesium ion token configured."); } }这里DefaultTokenAuthoring是 1.9 编辑阶段用的字段,运行时只读DefaultToken。很多新手只填了其中一个,导致编辑器里预览正常、打包运行后地形一片空白。脚本写在任意MonoBehaviour的Start里即可,注意FindObjectOfType要能在场景里找到 CesiumIonServer,找不到就说明三件套没创建完整。
3.2 用脚本把相机定位到目标城市
token 配好后,场景会加载全球地形,但视野还在原点附近,看起来像一片灰色网格。这时候需要把 Main Camera 绑定到 Cesium 坐标系上。最稳的做法是给相机加CesiumGlobeAnchor组件,然后在 Inspector 里直接填经纬高。
using CesiumForUnity; using UnityEngine; public class FlyToTarget : MonoBehaviour { public CesiumGeoreference georeference; [Range(0, 90)] public double latitude = 31.2304; [Range(0, 180)] public double longitude = 121.4737; [Range(0, 50000)] public double height = 2000; void Update() { if (Input.GetKeyDown(KeyCode.F)) { georeference.SetLongitudeLatitudeHeight( new CesiumGeoreference.LongitudeLatitudeHeight(longitude, latitude, height), true); } } }SetLongitudeLatitudeHeight第一个参数是经纬高对象,注意顺序是经度在前、纬度在后,写反了你会发现视角飞到海上去。第二个参数true表示立即移动整个坐标系,1.9 里这个参数还控制是否保持当前场景变换。如果你同时在场景里放了别的模型,true会把它们一起带着走,这是 Cesium 系里最常见的坐标“瞬移”行为,不是 bug。
3.3 动态切 tileset:按区域换数据的代码与参数
做城市级项目时,一个全球地形不够用,还要加载倾斜摄影或手工建模的 3D Tiles。创建Cesium3DTileset组件后,把Url改成你的 tileset.json 地址,然后如果还需要按运行时逻辑切换数据源,写脚本:
using CesiumForUnity; using UnityEngine; public class SwitchTileset : MonoBehaviour { public Cesium3DTileset targetTileset; public void LoadNewDataset(string url) { if (targetTileset == null) return; targetTileset.url = url; targetTileset.suspendedUpdate = false; targetTileset.maximumScreenSpaceError = 16f; } }url支持 http 和 https,也支持本地file://协议,但本地加载会在打包后有平台限制。suspendedUpdate = false是必须的,否则 tileset 停在挂起状态,永远不发瓦片请求。maximumScreenSpaceError默认 16,这个值是画质与帧率的命门,下一章专门说怎么调。
4. 1.9 性能与显示:四个必调参数,含摄像机与动态光照
4.1 MaximumScreenSpaceError 和 SuspendedUpdate 是一对跷跷板
Cesium 加载 3D Tiles 时,用屏幕空间误差(SSE)决定当前该加载哪一层瓦片。maximumScreenSpaceError越大,系统越愿意用粗糙的低层级瓦片,加载快、三角面少;越小越往精细层级钻,模型清晰但帧率断崖式下跌。1.9 的默认值 16 在室内小场景够用,一旦拉到城市级倾斜摄影,建议先调到 32 看帧率,再逐步降到 24、16。
SuspendedUpdate控制 tileset 是否主动调度瓦片更新。会动的场景里把它设成false,静态展示场景可以设true减少后台 CPU 占用。注意这两个参数互相影响:suspendedUpdate = true时,即使你改了 SSE 也不会立刻刷新瓦片,需要等下一帧唤醒。
4.2 动态光照下模型偏暗:需要区分 glTF 与地形
有同学在 Cesium for Unity 1.9 里加了一盏 Directional Light,发现建筑物背面死黑,地面却过曝。原因是加载进来的 3D Tiles 网格大多是 PBR 材质,光照响应依赖法线,而 Cesium 默认把 Unity 的烘焙光照强度按 1:1 映射。我一般会把平行光强度从默认 1 调到 1.2 到 1.5,并把Environment Lighting的环境光从 Skybox 改成 Color,灰度值 128 左右,这样夜间和白天场景都稳。
如果还是暗,检查模型本身的材质是不是用了Unlit。Cesium for Unity 1.9 对自定义 Shader 支持不完整,很多导入模型自带 Shader 在 URP 下直接显示粉紫色,这也是“动态光照怎么调都没反应”的常见原因。
4.3 摄像机跟随与遮挡剔除:这两个坑藏在默认配置里
Cesium for Unity 1.9 里 Camera 的控制方式和普通 Unity 游戏不同。给 Main Camera 挂上CesiumGlobeAnchor后,它的 transform 每帧会被 GlobeAnchor 拉回,你直接用transform.Translate会发现明明按了 W 却不动。正确做法是修改 anchor 的经纬高,或者读取 anchor 的position做本地偏移。
using CesiumForUnity; using UnityEngine; public class OrbitCamera : MonoBehaviour { private CesiumGlobeAnchor _anchor; public float rotateSpeed = 0.5f; void Start() { _anchor = GetComponent<CesiumGlobeAnchor>(); _anchor.longitudeLatitudeHeight = new CesiumGeoreference.LongitudeLatitudeHeight( 121.4737, 31.2304, 1500); } void Update() { if (Input.GetMouseButton(1)) { float deltaX = Input.GetAxis("Mouse X") * rotateSpeed; CesiumGeoreference.LongitudeLatitudeHeight llh = _anchor.longitudeLatitudeHeight; llh.longitude += deltaX; _anchor.longitudeLatitudeHeight = llh; } } }旋转视角的核心是改经纬度,不是改旋转角。1.9 里经纬高有一个最小步长,细微拖动时会感觉“一格一格跳”,把rotateSpeed调大一点反而更顺滑。
至于遮挡剔除,Unity 自带的 Occlusion Culling 对 Cesium 的流式网格基本无效,因为 3D Tiles 的瓦片是运行时动态创建和销毁的,烘焙静态遮挡数据时这些网格还不存在。想减少无效渲染,优先把Camera.farClipPlane从 1000 改成 300 到 500,效果立竿见影,很多远景空白其实是 LOD 还没加载到,不是剔除问题。
5. 避坑记录:从导入到运行最常见的 5 个翻车现场
5.1 tgz 导入时报 “Invalid package”
现象:Package Manager 选择 tarball 后弹出 “Invalid package”,或者解析卡在 50% 半小时不动。
原因:绝大多数情况是文件名带中文或空格,UPM 底层对非 ASCII 路径支持很差;另一部分是包文件下载不完整,package/package.json缺失。
解决:把文件重命名成纯英文短名称,例如cesium-unity-1.9.0.tgz,放在D:/cesium-packages这类无特殊字符的路径下。如果还报错,用tar -tzf看包内结构,确认第一条是package/package.json。改完路径后关掉 Unity 再重新打开一次,缓存的长路径旧引用才会清掉。
5.2 场景全紫或全黑,Cesium 菜单全消失
现象:装完包后现有场景的材质全部变成洋红色,或者菜单栏根本没有Cesium菜单项。
原因:1.9 分支对渲染管线有兼容性边界。如果你的工程启用了 URP 或 HDRP,Cesium 默认带的 Shader 走 Built-in 管线,跨管线编译后材质球失效,于是紫屏;菜单消失则是 Editor 程序集没编译成功,多半是与其他插件版本冲突。
解决:小工程直接把渲染管线切回 Built-in。在Project Settings > Graphics的Scriptable Render Pipeline Settings里置空即可。大工程不想切管线,就按官方方式给 Cesium 换 Shader,但这个工作量在 1.9 里明显大于 2.x,所以我建议新工程直接用 2.x,1.9 的包更偏学习和验证。
5.3 Cesium ion 页面能打开,Unity 里却一直转圈不加载
现象:地形数据在 ion 网页端预览正常,Unity 场景里 Cesium3DTileset 一直处于 loading 状态,Console 里偶尔出现 401。
原因:token 作用域不对。ion 的 token 分 asset 级和 account 级,你在网页端复制的 token 可能只授权了某一个数据集,而 Cesium World Terrain 用的另一个 asset 没被授权。还有一种情况是运行时代码里DefaultTokenAuthoring和DefaultToken只填了一个,打包后权限失效。
解决:在 Cesium ion 控制台创建一个 account token,勾选所有需要的 asset 权限,再把 token 同时填入DefaultToken和DefaultTokenAuthoring。如果只做本地验证,临时把 tileset 的 URL 替换成你导出的小范围 3D Tiles,绕开 ion 配额限制。
5.4 把 Web 端 Cesium 的 Entity 思维带进 Unity,画矩形画不出来
现象:很多人会去找cesium.entity、cesium.primitive对应到 Unity 的 C# API,结果发现CesiumForUnity程序集里根本没有 Entity 类,用 GameObject 画矩形又不断报错。
原因:Web 端 Cesium 的 Entity 和 Primitive 是 JavaScript 层面的抽象,对应到 Cesium for Unity 1.9,Entity 的位置被你手动创建的 GameObject 承担,Primitive 则落到 MeshRenderer 和 Collider。两者都不存在同名 API,硬找必然碰壁。
解决:换成“GameObject + 几何体 + CesiumGlobeAnchor”这套组合。在目标位置创建一个 Cube,挂上CesiumGlobeAnchor填经纬高,再拖到一个 3D Tiles 模型表面做吸附,这就是 Unity 版的“画矩形”。如果你需要真正的多边形图形,用 LineRenderer 围绕经纬点生成顶点,再把顶点坐标从经纬度转成 Unity 坐标,这是 1.9 里最容易被 Cesium 中文文档带偏的一个点。
5.5 相机飞到目标点后模型全部消失,像被挖掉一块
现象:相机靠近某个建筑物或地形细节时,网格突然消失,走远一点又出现,画面像被刀切过。
原因:这是浮点精度问题。Unity 的坐标用 float 存储,当你的相机离场景原点(通常是 Georeference 所在位置)超过几公里时,顶点抖动严重,Cesium 的裁剪逻辑会误判瓦片不可见。
解决:定期重置场景原点。把CesiumGeoreference的经纬高设回相机的当前位置,让 Unity 坐标原点跟着人走。在代码里就是每移动一段距离调用一次SetLongitudeLatitudeHeight(当前位置)。这个操作会触发所有 tileset 重新调度,不要每帧调用,建议位移超过 500 米才重置一次。
6. 进阶验证:本地化 3D Tiles 与向 2.x 升级前的检查项
先解决一个高频诉求:断了外网、不想申请 token,能不能用 1.9。答案是能,但要把流数据源本地化。你可以用 Cesium terrain builder(CTB)把本地 DEM 切成分块地形,或者用数据转换工具把倾斜摄影转成 3D Tiles,放到一个本地服务器里。1.9 对 MVT 这类矢量瓦片不能直接读,必须先转成 3D Tiles 或 GeoJSON 再投喂给 Cesium3DTileset。启动本地服务最省事的方式:
cd D:/all-3dtiles python -m http.server 8080然后把Cesium3DTileset的 URL 改成http://localhost:8080/tileset.json,token 字段留空即可。注意本地服务器要正确返回Content-Type: application/json,python 自带的http.server对 .json 的 MIME 处理正常,但如果文件名带大写后缀会误判,叫tileset.JSON就等着报解析错误吧。
本地化方案适合验证数据生产流程,不适合做交付产品。真要发包给客户,还是建议走 ion 鉴权,或者把数据打到对象存储上再配 CDN,Cesium 的瓦片请求是海量的小文件,单台服务器扛不住几十个并发用户。
最后说升级。如果你正用 1.9,别急着删包,先列一个验证清单:CesiumGeoreference的 API 名、Cesium3DTileset的默认 SSE 值、Cesium 菜单的创建路径,这三样在 2.x 里有不少变化。有同事升级后出现“找不到SetLongitudeLatitudeHeight方法”,就是 API 改名造成的。我的习惯是先在旁边开一个新工程装 2.x,用离线 3D Tiles 跑通同等场景,对比帧率和包体大小,再决定整个项目是否迁移。这样既不会被 1.9 的旧坑继续困住,也不至于在升级过程中把线上工程的坐标基准弄乱。
希望这些经验能帮你把 1.9 的包文件用明白,少走几个弯。
本文还有配套的精品资源,点击获取