在 3DGS 场景中行走:碰撞支持
LCC4Unreal 支持动态碰撞数据加载,角色可在 3DGS 世界中自由走动和交互。
前置条件
碰撞依赖数据自带的碰撞文件,不同格式的要求不同:
| 格式 | 碰撞数据 | 支持情况 |
|---|---|---|
.lcc | 数据目录下的 collision.lci,旧版本为 collision.bin | 支持 |
.lcc2 | 数据目录下 data/mesh/ 中的 .ply 文件 | 支持 |
.sog / .spz / .ply | 本身不含,专业版可从高斯自动派生 | 支持(专业版) |
对于 .lcc 与 .lcc2,插件按 collision.lci → collision.bin → data/mesh/*.ply 的顺序检测数据自带的碰撞文件,三者都不存在时输出警告并禁用碰撞。
单文件格式(.sog / .spz / .ply)本身不携带碰撞数据。专业版可从高斯自动派生碰撞网格,见单文件模型的碰撞自动生成;免费版需自行搭建碰撞。
加载数据后可用 HaveValidCollisionData() 确认当前数据是否包含可用的碰撞数据。
注:
collision.lci需要 LCC Studio v1.6.1 及以上版本导出,更早版本导出的数据使用collision.bin。
加载机制
碰撞数据和渲染数据一样按空间分块存储。插件不会一次性加载全部碰撞,而是只加载相机周围一定范围内的块,并随相机移动动态换入换出。
相机位置变化
│
▼
计算范围内应加载的碰撞块集合
│
▼
与上一次的集合比较 ── 相同 ──▶ 跳过,不做任何处理
│ 不同
▼
加载新增的块 → 交给物理系统烘焙 → 生成碰撞体
几个实现上的要点:
- 加载范围由
Max Load Collision Distance(m)控制,超出该距离的区域没有碰撞 - 首次加载是同步的,避免角色在碰撞尚未就绪时穿过地面掉落;之后的更新都走异步,不阻塞主线程
- 有频率节流,相机连续移动时不会每帧都重建碰撞
- 可见块集合未变化时直接跳过,原地小幅移动不会触发重建
- 只按主相机计算,SceneCapture 不参与碰撞加载
优点
- 内存占用只与加载范围有关,与数据总量无关,大场景也能支持碰撞
- 物理系统需要处理的碰撞体数量始终可控,不会因为场景规模增长而拖慢物理计算
代价与规避
| 问题 | 原因 | 规避方式 |
|---|---|---|
| 开始游戏瞬间角色穿地掉落 | 碰撞尚未构建完成 | 把 PlayerStart 抬高一段距离,或在碰撞就绪后再启用角色移动 |
| 角色从远处进入 3DGS 场景范围时卡顿 | 角色出生在碰撞加载范围外,首次进入时触发同步加载 | 让角色出生点位于碰撞加载范围内,或一次性加载全部碰撞 |
| 远处没有碰撞,射线检测打不中 | 超出加载范围的区域不生成碰撞体 | 调大 Max Load Collision Distance(m),或改用不依赖碰撞的判断方式 |
| 传送或快速移动后短时间内无碰撞 | 新区域的碰撞块还在加载 | 一次性加载全部碰撞 |
移动中出现卡顿,Update Collision 耗时高 | 碰撞块频繁换入换出并重新烘焙 | 缩小加载范围,或确认是否真的需要碰撞 |
| 配合导航时导航网格反复重建 | 碰撞变化触发 NavMesh 更新 | 调大加载范围让目标区域一次性加载完,并使用 Static 烘焙,详见寻路系统支持 |
一次性加载全部碰撞
上述代价大多来自运行期的动态换入换出。如果场景规模有限、内存有余量,可以把 Max Load Collision Distance(m) 调大到足以覆盖整个场景,让碰撞在加载数据时一次性全部建好。
这样运行期不再有碰撞块的换入换出,前面表格里的穿地掉落、传送无碰撞、移动卡顿、导航反复重建都不会出现,配合寻路系统时尤其推荐。
代价是启动时的加载时间变长、内存占用固定为全场景碰撞的大小。判断是否可行:查看 stat xgrids 中的 Collision Data Usage,确认全量加载后的内存占用在可接受范围内。
开启
LCCComponent->SetLCCCollisionEnable(true);
或在 Details 面板中勾选 bEnableCollision。

在 Details 面板中启用 LCC 碰撞

角色在 LCC 场景中的动态碰撞效果
验证
通过视图模式设置,选择玩家碰撞或可视性碰撞可以观察到碰撞是否已开启

使用玩家碰撞或可视性碰撞模式验证碰撞体
相关属性
| 属性 | 说明 |
|---|---|
| bEnableCollision | 启用碰撞 |
| CollisionLoadMaxDistance | 碰撞数据最大加载距离(默认 300 米) |

配置碰撞启用状态与最大加载距离
单文件模型的碰撞自动生成(专业版功能)
单文件模型(.ply / .spz / .sog)本身不含碰撞数据,插件会从高斯本身派生出碰撞网格,缓存为模型旁的 <名字>.collision.ply,之后通过既有的 PLY 碰撞路径加载复用。
这是专业版功能,需要注册 App Key 后才会生成,详见版本与授权。未授权时不生成碰撞网格,需按不使用自动生成时的手动方案自行搭建。
使用步骤
- 在 LCC Actor 面板勾选 bEnableCollision。
- 加载单文件模型(
.ply/.spz/.sog)。 - 首次加载会进入
Generating状态现场生成碰撞网格,耗时数秒到数分钟,取决于数据量;生成完成后转入Loaded,并在模型旁写出<名字>.collision.ply。 - 之后再加载同一模型,若缓存文件存在则直接
Loaded,跳过生成。

勾选启用碰撞后,单文件模型首次加载时右下角提示正在生成碰撞网格
生成与碰撞的状态可通过 GetCollisionState() 查询,或监听 OnCollisionStateChanged 事件,取值见 ULCCComponentBase - 状态查询。
提示:想让运行时免生成,把生成好的
<名字>.collision.ply随模型一起分发或打包即可,运行时检测到缓存会直接复用。提示:打包游戏里生成碰撞时没有内置 UI 提示,要告知玩家"正在生成碰撞",请监听
OnCollisionStateChanged的Generating状态自行显示。提示:生成失败会转入
Failed状态,具体原因见 Output Log,关闭再重新开启碰撞可重试。想重新测试生成过程,先删除模型旁的.collision.ply缓存文件。
不使用自动生成时的手动方案
如果想完全控制碰撞形状,或数据不适合派生,也可以不开自动生成,自行在场景中搭建碰撞:
- Blocking Volume:用引擎的阻挡体积拼出地面、墙面等需要阻挡的区域,适合规则形状,成本最低
- 近似网格:放置一份与 3DGS 形状贴合的网格并启用其碰撞,适合形状复杂的场景。这份网格可以复用代理网格,把它的碰撞预设改为参与阻挡即可
手动搭建的这两种方式与 LCC 的碰撞加载机制无关,不受 CollisionLoadMaxDistance 影响,也不会随相机移动动态换入换出。
裁剪碰撞区域
碰撞可以随裁剪体与剖切面一起被裁剪,使碰撞范围与渲染画面保持一致。裁剪体默认只影响渲染,被裁掉的区域画面消失但碰撞仍在,角色会撞到看不见的墙;开启裁切碰撞后,碰撞也会在裁剪区域内同步去除。
使用步骤
- 按场景编辑给 LCC Actor 添加并配置裁剪体或剖切面,确认渲染画面已按预期裁剪。
- 在 LCC Actor 面板勾选 启用碰撞(bEnableCollision)。
- 在面板勾选 裁切碰撞,碰撞随即按裁剪体裁剪,被裁区域不再生成碰撞体。
下图用「可视性碰撞」视图模式对比裁切碰撞开关前后的碰撞线框。关闭时碰撞覆盖完整区域:

未勾选「裁切碰撞」:碰撞线框覆盖完整区域
开启后,裁剪体内的碰撞被一并裁掉,与渲染一致:

勾选「裁切碰撞」:裁剪区域内的碰撞被一并裁掉
提示:裁切碰撞需要先启用碰撞,对单文件模型自动生成的碰撞同样有效。
碰撞状态查询与事件
可以查询碰撞当前的状态,或监听碰撞状态变化,用于"碰撞就绪再放角色""生成中显示进度"等逻辑:
GetCollisionState()返回当前状态:NoCollision(关闭或无模型)/Generating(单文件模型正在生成碰撞网格)/Loading(相机附近碰撞加载/cook 中)/Loaded(相机附近碰撞就位)/Failed(无法提供)。OnCollisionStateChanged事件在状态变化时派发,可在Loaded后再启用角色移动,或在Generating时显示提示。
完整接口与使用约定见 ULCCComponentBase - 状态查询。
提示:
Loaded指相机附近的碰撞就位,不代表整个模型都有碰撞——碰撞随相机移动持续流式加载。需要"脚下不穿地"时等Loaded即可;需要远处碰撞请调大加载距离。
注意事项
- 开启碰撞后可使用 UE 引擎自身的 LineTrace 进行基于碰撞体的射线检测,检测范围同样受加载范围限制
- 碰撞数据占用的内存可在
stat xgrids的Collision Data Usage中查看,更新耗时见Update Collision,参数含义见性能优化参数说明