碰撞系统开发指南
LCC Unity SDK 内建了一套碰撞系统,重点解决碰撞体构建与碰撞检测的加速问题,也就是碰撞性能问题。Unity Collider 系统无法应付超大场景下的实时检测。
LCC Unity SDK 采用自建碰撞系统,不再借助 Unity 提供的 MeshCollider 组件及相关能力,因此不能直接对 Unity 场景中的 GameObject 产生作用。其域创新(XGrids)官方生成的 LCC 数据格式( LCC Studio )在重建时会同时生成用于碰撞的 Mesh 数据,SDK 利用这份碰撞数据快速高效地构建场景碰撞。由于是自建碰撞系统,使用碰撞功能需要调用 SDK 提供的相应方法来实现。
注意:
SDK 内建碰撞系统与 Unity Collider 碰撞系统不兼容,无法直接作用于 Unity 中的
Rigidbody对象。数字人等角色的碰撞需要通过 SDK 的检测方法自行驱动(见下文「数字人碰撞实现方式」)。如果是固定场景,也可以将 Mesh 数据提取出来提前烘焙成 NavMesh ,可与 Unity Collider 碰撞系统实现兼容,详见 NavMesh 指南。
数据前置条件
碰撞检测功能生效的前提是场景带有对应的碰撞数据。早期版本重建的数据可能不包含碰撞数据,此时调用 SetColliderEnable(true) 会返回 false,后续所有检测方法都不可用。
因此在开启碰撞后,请务必检查返回值:
bool ok = renderer.SetColliderEnable(true);
if (!ok)
{
Debug.LogWarning("当前数据不含碰撞体,无法开启碰撞检测");
}
基本使用流程
碰撞功能的基本使用流程分三步:
- 通过
Load()方法加载场景数据。 - 在加载完成回调中,通过
SetColliderEnable(true)开启碰撞。 - 通过各类检测方法(
RaycastMesh/IntersectsSphere/IntersectsCapsule)进行碰撞检测。
// 1. 加载场景
renderer.Load(dataPath, onProgress: null, onComplete: () =>
{
// 2. 加载完成后开启碰撞
if (renderer.SetColliderEnable(true))
{
colliderReady = true;
}
});
void Update()
{
if (!colliderReady) return;
// 3. 每帧进行碰撞检测
var capsule = new Capsule(footPos, headPos, 0.3f);
if (m_manager.IntersectsCapsule(capsule, out Vector3 delta))
{
characterController.Move(delta);
}
}
说明:
SetColliderEnable()是Renderer的方法,检测方法(RaycastMesh/IntersectsSphere/IntersectsCapsule/Raycast)挂在LCCManager上。请分别在对应对象上调用。

碰撞系统基本使用流程
数字人碰撞实现方式
由于 SDK 碰撞系统不作用于 Unity 的 Rigidbody,数字人(角色)的碰撞需要用检测方法自行驱动。常见做法有三种:
- 双射线检测:使用
RaycastMesh()向下、向前各发射一条射线,通过射线返回结果判断能否行走(向下探地面、向前探障碍)。 - 胶囊体检测:使用
IntersectsCapsule()检测数字人所在的胶囊体与碰撞网格是否相交,判定能否行走。重载版本的_delta返回下一个可安全到达的点的偏移量。 - 球体检测:使用
IntersectsSphere()检测数字人所在的球体与碰撞网格是否相交,判定能否行走。重载版本的_delta同样返回可安全到达点的偏移量。

数字人碰撞的三种实现方式
RaycastMesh 与 Raycast 的取舍
SDK 提供两类射线检测方法,用途不同:
| 方法 | 检测对象 | 精度 | 速度 | 适用场景 |
|---|---|---|---|---|
RaycastMesh() | 碰撞网格(Collider 数据) | 相对较低 | 快 | 数字人碰撞、逐帧检测 |
Raycast() | 高斯基元(不依赖碰撞网格) | 相对较高 | 慢 | 测量类应用 |
Raycast() 直接对高斯基元进行射线检测,精度更高,但速度慢,不建议每帧调用,因此不适合做数字人碰撞,只适合做测量类使用。数字人碰撞应优先使用依赖碰撞网格的 RaycastMesh()。
相关 API
以下碰撞相关方法中,SetColliderEnable() 挂在 Renderer 上,其余检测方法挂在 LCCManager 上。所有检测方法都需要在场景加载完成后、且成功调用 SetColliderEnable(true) 之后才可用。
SetColliderEnable
// 返回值:bool → true=设置成功,false=数据不含碰撞体或实例未激活
public bool SetColliderEnable(bool _enable)
开关碰撞体功能。启用后 IntersectsSphere / IntersectsCapsule / RaycastMesh 才可用。
| 参数 | 类型 | 说明 |
|---|---|---|
_enable | bool | 是否启用碰撞体 |
调用示例:
bool ok = renderer.SetColliderEnable(true);
if (!ok) Debug.LogWarning("数据不含碰撞体");
说明:
- 数据必须包含碰撞(Mesh)数据,否则返回
false。 - 需要
Renderer处于激活状态。
RaycastMesh(屏幕坐标)
// 返回值:bool → true=命中
public bool RaycastMesh(Vector3 mousePos, out HitResult _finalResult, float _distance= 70.0f)
从屏幕坐标发射射线检测碰撞网格。使用 Collider 数据检测,比 Raycast 更快但精度较低。
| 参数 | 类型 | 说明 |
|---|---|---|
mousePos | Vector3 | 屏幕坐标 |
_finalResult | out HitResult | 命中结果 |
_distance | float | 最大检测距离,默认 70.0 |
调用示例:
if (m_manager.RaycastMesh(Input.mousePosition, out HitResult hit))
{
Debug.Log(hit.hitPos);
}
说明:
- 需要先成功开启碰撞。
- 需先调用
SetColliderEnable(true)。
RaycastMesh(Ray + Bounds)
// 返回值:bool → true=命中
public bool RaycastMesh(Ray ray, out HitResult result, out Bounds hitBounds, float maxDist = 70.0f)
使用自定义 Ray 进行碰撞网格检测,同时返回命中节点的包围盒信息。
| 参数 | 类型 | 说明 |
|---|---|---|
ray | Ray | 射线 |
result | out HitResult | 命中结果 |
hitBounds | out Bounds | 命中节点的包围盒(命中的 LOD 节点包围盒) |
maxDist | float | 最大检测距离,默认 70.0 |
调用示例:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (m_manager.RaycastMesh(ray, out HitResult hit, out Bounds bounds))
{
Debug.Log(bounds.center);
}
说明:
- 需要先成功开启碰撞。
- 双射线检测(向下、向前)判断数字人能否行走时常用此方法。
IntersectsSphere
// 返回值:bool → true=相交
public bool IntersectsSphere(Sphere sphere)
// 返回值:bool → true=相交
public bool IntersectsSphere(Sphere sphere, out Vector3 delta)
检测球体与碰撞网格是否相交。第二个重载额外返回穿透向量 delta(推出方向与距离),可用于计算下一个可安全到达的点。
| 参数 | 类型 | 说明 |
|---|---|---|
sphere | Sphere | 待检测的球体 |
delta | out Vector3 | 穿透向量(推出方向和距离) |
调用示例:
var sphere = new Sphere(transform.position, 0.5f);
if (m_manager.IntersectsSphere(sphere, out Vector3 delta))
{
transform.position += delta;
}
说明:
- 需要先成功开启碰撞。
- 需先调用
SetColliderEnable(true)。 - 遍历所有激活的
Renderer。
IntersectsCapsule
// 返回值:bool → true=相交
public bool IntersectsCapsule(Capsule capsule)
// 返回值:bool → true=相交
public bool IntersectsCapsule(Capsule capsule, out Vector3 delta)
检测胶囊体与碰撞网格是否相交。常用于角色控制器碰撞检测。第二个重载返回穿透向量 delta,可作为数字人下一个可安全到达的点偏移。
| 参数 | 类型 | 说明 |
|---|---|---|
capsule | Capsule | 待检测的胶囊体 |
delta | out Vector3 | 穿透向量 |
调用示例:
var capsule = new Capsule(footPos, headPos, 0.3f);
if (m_manager.IntersectsCapsule(capsule, out Vector3 delta))
{
characterController.Move(delta);
}
说明:
- 需要数据包含碰撞节点。
- 需先调用
SetColliderEnable(true)。 - 适合第一人称 / 第三人称角色碰撞。
Raycast
// 返回值:bool → true=命中
public bool Raycast(Ray _ray, out HitResult _finalResult)
使用自定义 Ray 对高斯基元进行射线检测,遍历所有激活的 Renderer 返回最近命中。不依赖碰撞网格,精度较高但速度慢。
| 参数 | 类型 | 说明 |
|---|---|---|
_ray | Ray | 射线 |
_finalResult | out HitResult | 命中结果 |
调用示例:
Ray ray = new Ray(origin, direction);
if (m_manager.Raycast(ray, out HitResult hit))
{
Debug.Log(hit.hitPos);
}
说明:
- 不依赖碰撞网格,无需
SetColliderEnable。 - 精度较高但速度慢,不建议每帧调用,适合测量类应用,不适合数字人碰撞。
HitResult
上述检测方法的命中结果通过 HitResult 结构体返回:
public struct HitResult {
public bool isHit; // 是否命中
public float distance; // 距离
public Vector3 hitPos; // 命中点世界坐标(字段名为 hitPos,非 position)
public Vector3 normal; // 命中法线
public float hitAlpha; // 被击中椭球的 Alpha
public float dist2Origin; // 到射线源的距离
public float scale; // 椭球 scale
}
注意:
命中点世界坐标的字段名是
hitPos,不是position;请按实际字段名访问。