LineTraceSingleByChannel 返回 false 不一定没打中,常见原因是射线起点在碰撞体内部导致被忽略;HitResult.Location 为 (0,0,0) 是未命中时的未定义值,须先检查函数返回值才能安全使用 Hit。

LineTraceSingleByChannel 返回 false 是不是没打中?
不一定。返回 false 只代表「没有命中任何可碰撞的物体」,但常见原因其实是射线起点在某个碰撞体内部——Unreal 默认会忽略从内部发起的射线(即“inside-out”情况)。此时即使目标就在正前方,LineTraceSingleByChannel 也会直接返回 false,不报错也不警告。
实操建议:
- 用
DrawDebugLine可视化射线:确认起点、终点坐标和方向是否符合预期,尤其注意Start是否意外处于角色胶囊体或场景静态网格内部 - 临时把
bTraceComplex设为true测试:复杂碰撞更敏感,若此时能命中,基本可锁定是简单碰撞体(Simple Collision)未启用或形状不匹配 - 检查目标 Actor 的
Collision Enabled是否为NoCollision或QueryOnly—— 若设为PhysicsOnly,则LineTraceSingleByChannel(默认只做查询)完全无法命中
HitResult 里为什么 Location 是 (0,0,0)?
这是最典型的未命中伪影:LineTraceSingleByChannel 返回 false 时,OutHit 参数不会被写入,其内容是内存残留值(常表现为 FVector::ZeroVector)。不能靠检查 HitResult.Location 是否为零来判断是否命中,必须先检查函数返回值。
正确写法示例:
立即学习“C++免费学习笔记(深入)”;
FHitResult Hit;
if (GetWorld()->LineTraceSingleByChannel(
Hit,
Start,
End,
ECC_Visibility, // 注意通道要和目标碰撞预设匹配
CollisionParams))
{
// ✅ 此时 Hit 才有效,Location / Actor / Component 等字段可安全使用
DrawDebugSphere(GetWorld(), Hit.Location, 10.f, 12, FColor::Green, false, 0.1f);
}
else
{
// ❌ 这里 Hit.Location 是未定义值,不要读取
}
容易踩的坑:
- 把
Hit声明为类成员变量并复用:多次调用后未命中的结果会污染上次的有效数据 - 误用
ECC_Camera通道:该通道默认对大多数静态网格禁用,除非你显式设置了bTraceComplex或调整了碰撞预设
怎么让射线穿过透明物体只打到后面的实体?
Unreal 默认射线遇到第一个可碰撞物就停止,要穿透需改用 LineTraceMultiByChannel,再手动过滤掉透明/不可交互对象。
关键控制点:
- 用
FCollisionQueryParams的bReturnPhysicalMaterial和AddIgnoredActor配合逻辑判断,但更常用的是在LineTraceMultiByChannel结果中遍历筛选 - 给透明物体(如玻璃、UI面板)设置独立碰撞通道(例如
ECC_GameTraceChannel1),并在射线参数中通过FCollisionResponseContainer将该通道设为ECR_Ignore - 性能注意:多段射线比单段开销明显上升,若仅需「最近非透明物」,建议用
LineTraceSingleByChannel+ 多次重试(每次跳过上一次命中物)更轻量
蓝图里能直接调用 LineTraceSingleByChannel 吗?
不能直接调用 C++ 版本,但蓝图有等效节点:Line Trace By Channel(非 By Object Type)。它的底层就是封装了 LineTraceSingleByChannel,行为一致。
对应关系要注意:
- 蓝图中勾选
Trace Complex≡ C++ 中传入FCollisionQueryParams并设bTraceComplex = true - 蓝图里的
Collision Profile Name下拉项,对应 C++ 中的ECollisionChannel枚举值(如ECC_Visibility) - 蓝图节点输出的
Hit结构体字段名和 C++FHitResult完全一致,包括Location、Normal、Distance等
真正容易被忽略的是:蓝图节点默认不绘制调试线,想可视化必须手动勾选 Draw Debug Type 并设为 For One Frame 或 Permanent —— 很多人调了半天没结果,其实只是射线根本没画出来,无从验证方向和长度。


















