简介:这份离线插件包面向使用 Unity 开发三维地理可视化项目的开发者,尤其是因网络受限、公司内网或 Package Manager 拉取失败而无法在线安装 Cesium for Unity 1.17.0 的人群。压缩包为 tgz 格式,共 1158 个文件,体积约 316.6MB,内容以 580 个 meta 元数据、208 个 pc 着色器变体、150 个 cs 脚本、136 个 a 静态库及 png、svg、dll、dylib、asmdef、shadergraph 等为主,覆盖运行时脚本、原生库、材质与着色器、程序集定义等完整模块,可离线导入并正常参与编译。目前已有 412 人学习下载。对于需要搭建 Cesium 三维地球、加载 3D Tiles 与影像图层、研究原生库依赖或排查包管理安装失败的读者,这份资源能省去在线拉取与版本匹配的麻烦,直接获得可用的工程依赖与目录结构,便于对照文章完成导入与验证。
1. 离线插件包到底解决了什么:从一次内网部署翻车说起
把 Cesium for Unity 1.17.0 的离线插件包丢进一个没有外网出口的工程环境,这件事听起来只是「下载再导入」,实际做过的都知道,翻车点往往不在插件本身,而在依赖链和缓存路径。Cesium for Unity 是把 3D Tiles 流式加载、地理坐标转换、全球地形与影像调度带进 Unity 的运行时组件,常规安装走的是包管理器在线拉取,而离线插件包就是把这一整套依赖提前固化成一个可拷贝的本地包。它解决的核心问题是:内网机器、隔离网段、展会现场、客户演示机这些不能稳定访问外网的场景下,仍然能把 Cesium 世界地形跑起来。
适合谁?做数字孪生、GIS 可视化、Unity 地图类项目的开发者,尤其是需要把工程交付到别人机器上、又不想让对方折腾网络环境的人。这一章先把「离线包是什么、为什么需要它、边界在哪」讲清楚,后面几章再拆导入、配置、排错和进阶技巧。一句话结论:离线插件包不是万能药,它只保证「包能进来」,不保证「地形能下载」——这两件事必须分开对待。
2. 离线包导入 Unity 的完整路径:从包结构到第一次运行
2.1 先看清离线包里有什么,再决定怎么导入
拿到一个 Cesium for Unity 1.17.0 离线插件包,第一件事不是双击,而是先解压看目录。常见做法是把它组织成一个本地 UPM 包或者一个.unitypackage,两种形态的导入方式完全不同。我一般会先确认三样东西:package.json是否存在、Runtime与Editor目录是否齐全、有没有附带原生库(Plugins下的.dll/.so/.bundle)。少了原生库,编辑器里能编译,一运行就报找不到符号。
# 查看离线包顶层结构,确认是 UPM 包还是 unitypackage ls -la CesiumForUnity-1.17.0-offline/ # 典型 UPM 包应包含: # package.json Runtime/ Editor/ Plugins/ Documentation~/逻辑说明:package.json决定这个包能不能被 Unity 包管理器识别为本地包;Runtime放运行时脚本和程序集定义;Editor放编辑器扩展;Plugins放各平台原生库。参数上重点看package.json里的name、version、dependencies——如果dependencies里写了别的包,而离线环境没有,导入后照样报错。
2.2 用本地包方式导入,避免污染全局缓存
推荐做法是把离线包放到工程目录外的固定路径,然后通过 Package Manager 的「Add package from disk」指向它的package.json。这样升级和回滚都干净,不会把文件散落到Library/PackageCache里难以追踪。
{ "name": "com.cesium.unity", "version": "1.17.0", "displayName": "Cesium for Unity", "dependencies": { "com.unity.mathematics": "1.2.6" } }逻辑说明:这是离线包package.json的典型结构。dependencies里声明的com.unity.mathematics必须在本机可用,否则包管理器会卡在解析阶段。参数说明:version必须和离线包实际版本一致,手动改版本号会导致程序集引用错位;name不要改,改了之后场景里已挂载的组件会丢失引用。
导入完成后,在 Unity 里新建一个空场景,挂一个CesiumGeoreference,再挂Cesium3DTileset,这是验证包是否可用的最小组合。如果 Inspector 里能看到组件且不报编译错误,说明包本身没问题。
2.3 第一次运行前必须确认的三个开关
很多人导入成功就以为完事,结果一运行黑屏。常见原因是三个地方没配:一是CesiumGeoreference的经纬度没设,默认原点在 (0,0),相机可能离地球表面几万公里;二是Cesium3DTileset的Url指向了一个需要联网的瓦片服务;三是 Unity 的脚本后端和 API 兼容级别不匹配。
// 最小验证脚本:把相机放到指定经纬度上方 using CesiumForUnity; using UnityEngine; public class CesiumQuickStart : MonoBehaviour { public CesiumGeoreference georeference; public double longitude = 116.39; public double latitude = 39.9; public double height = 2000.0; void Start() { // 设置地理原点,单位:度、度、米 georeference.longitude = longitude; georeference.latitude = latitude; georeference.height = height; } }逻辑说明:CesiumGeoreference负责把 WGS84 坐标映射到 Unity 世界坐标,原点设错,后面所有物体位置都会偏。参数说明:longitude/latitude用十进制度,height是椭球高不是海拔高,两者在海平面附近差几十米,做精确对齐时要注意。这个脚本只做原点设置,不涉及瓦片下载,适合先验证坐标转换是否正确。
3. 离线环境下让地形真正显示:瓦片数据与缓存策略
3.1 离线包不等于离线数据,这是两码事
这是最容易混淆的地方。Cesium for Unity 1.17.0 离线插件包只包含代码和原生库,不包含全球地形和影像瓦片。要让地形显示,要么提前把瓦片缓存到本地,要么在内网自建瓦片服务。我一般会先问清楚:你是要「完全离线」还是「内网可达」?前者需要把瓦片预下载成 3D Tiles 目录,后者只需要一个内网 HTTP 服务。
预下载的常见做法是用 Cesium 官方的瓦片工具把指定范围的 terrain 和 imagery 导出成本地目录,然后在Cesium3DTileset的Url里填file://或本地服务地址。注意file://在部分平台会被安全策略拦截,内网 HTTP 更稳。
3.2 本地瓦片服务的目录结构与 Url 写法
把瓦片放到一个静态目录,用任意 HTTP 服务器暴露出来即可。关键是tileset.json的相对路径不能错,否则加载器会 404 但只在 Console 里给一行警告,很容易被忽略。
# 假设瓦片目录结构如下 # /data/tilesets/terrain/tileset.json # /data/tilesets/terrain/0/0/0.b3dm # 用 Python 起一个最简静态服务 cd /data/tilesets python -m http.server 8080逻辑说明:tileset.json是 3D Tiles 的入口,里面用相对路径引用子瓦片,所以 HTTP 服务的根目录必须是tileset.json所在目录的上一级或同级。参数说明:端口 8080 只是示例,内网部署时确认防火墙放行;如果瓦片是 gzip 压缩的,服务端要正确设置Content-Encoding,否则加载器解压失败。
在 Unity 侧,Cesium3DTileset的Url填http://内网IP:8080/terrain/tileset.json。如果加载后地形是平的,先看 Console 有没有404或CORS报错,再看tileset.json里的geometricError是否合理——这个值太大,远处瓦片不加载;太小,近处瓦片过多。
3.3 缓存目录与磁盘占用控制
Cesium for Unity 运行时会往本地缓存目录写已下载的瓦片,默认在Application.persistentDataPath下。离线环境里这个缓存是好事,但磁盘小的机器要提前规划。
| 参数 | 默认行为 | 建议调整 |
|---|---|---|
| 缓存路径 | persistentDataPath/Cesium | 大工程改到独立数据盘 |
| 最大缓存 | 无硬上限 | 按磁盘容量设上限,定期清理 |
| 瓦片并发 | 运行时自适应 | 内网带宽低时手动调小 |
逻辑说明:缓存路径可以通过运行时 API 修改,但要在创建Cesium3DTileset之前设置。参数说明:并发数调小能降低内网压力,但会拖慢首次加载;磁盘上限建议留出至少 20% 余量,否则写入失败会导致瓦片反复重下。
4. 避坑与排查:离线部署里最常见的五类翻车
4.1 导入后组件变紫或材质丢失
现象:场景里 Cesium 相关物体显示为紫红色,Console 报 shader 找不到。原因:离线包里的 shader 依赖 Unity 内置管线或特定渲染管线,而工程用的是另一套。解决:确认工程渲染管线与包要求一致,URP/HDRP 工程要导入对应的 shader 变体,必要时重新导入包并勾选全部平台。
4.2 运行时报找不到原生库
现象:编辑器里正常,打包后运行报DllNotFoundException。原因:离线包的Plugins目录没有包含目标平台的原生库,或者平台开关没勾。解决:检查Plugins下是否有对应平台的.dll/.so/.bundle,在 Inspector 里确认该平台的勾选状态,重新打包。
4.3 地形加载一半就停
现象:近处地形出来了,远处一直空白。原因:tileset.json的geometricError或maximumScreenSpaceError设置不当,或者内网服务在大文件上超时。解决:先调大maximumScreenSpaceError看是否恢复,再检查服务端对大文件的响应时间,必要时把瓦片切得更细。
4.4 坐标偏移几百米
现象:模型和地形对不上,整体偏移。原因:CesiumGeoreference的原点设置和数据的坐标系不一致,或者高度基准用错(椭球高 vs 海拔高)。解决:统一用 WGS84 经纬度加椭球高,确认数据源的坐标系,必要时在导入前做一次坐标转换。
4.5 打包后包体异常增大
现象:接入 Cesium 后安装包体积翻倍。原因:离线包里的原生库和 shader 变体被全平台打进包,或者缓存目录被误打包。解决:在 Player Settings 里按目标平台裁剪,排除不需要的平台库;确认缓存目录不在Assets下,不会被自动打包。
5. 进阶技巧:把离线包用成可维护的工程资产
5.1 用脚本化导入替代手动操作
手动导入一次两次还行,团队协作时容易版本不一致。我一般会写一个编辑器脚本,在工程打开时检查本地包路径并自动添加依赖,这样换机器不用重新点一遍。
// 放在 Editor 目录下,工程加载时检查 Cesium 包是否存在 using UnityEditor; using UnityEditor.PackageManager; using UnityEngine; [InitializeOnLoad] public static class CesiumOfflineBootstrap { const string PackagePath = "file:../packages/CesiumForUnity-1.17.0-offline"; static CesiumOfflineBootstrap() { // 延迟一帧,等包管理器初始化完成 EditorApplication.delayCall += CheckAndAdd; } static void CheckAndAdd() { var list = Client.List(true); list.Completed += (req) => { foreach (var pkg in req.Result) { if (pkg.name == "com.cesium.unity") return; // 已存在 } // 未安装则从本地路径添加 Client.Add(PackagePath); Debug.Log("Cesium 离线包已自动添加"); }; } }逻辑说明:Client.List异步查询已安装包,回调里判断是否已有com.cesium.unity,没有才Client.Add。参数说明:PackagePath用相对路径指向离线包,团队里每个人把包放在工程同级目录即可;Client.Add是异步的,不要在它后面立刻访问 Cesium 类型。
5.2 用版本锁定避免「昨天还好今天崩了」
离线包最大的价值是可复现。把package.json里的版本号固定,并在工程里提交Packages/manifest.json和packages-lock.json,这样任何人拉下来都是同一套依赖。我见过太多因为某台机器上包管理器偷偷升级了依赖导致地形加载行为不一致的案例,锁定版本是唯一的后悔药。
5.3 验证离线包是否真的离线可用
最后给一个自检清单:断网后打开工程,确认包管理器不报网络错误;运行场景,确认地形从本地服务加载;打包到目标平台,确认原生库齐全。这三步都过,才算真正把离线插件包用明白了。
我自己踩过最深的一个坑,是以为导入成功就等于离线可用,结果客户现场断网后地形一片空白,才发现瓦片服务还指着外网。从那以后,我养成了一个习惯:任何离线部署,先在完全断网的机器上跑一遍最小场景,再谈交付。希望帮到你。
本文还有配套的精品资源,点击获取