UE5中Multi Line Trace by Channel导致引擎崩溃问题排查
问题原因与修复方案
崩溃根源
代码崩溃的核心原因是for循环终止条件错误:sizeof(hits)获取的是TArray容器自身的内存大小(通常是16字节左右,对应几个内部指针的尺寸),而非数组中FHitResult元素的实际数量。当循环索引i超过数组真实元素个数后,会访问内存边界外的非法区域,触发内存错误导致引擎崩溃。
修复后的代码
方案1:用TArray::Num()获取元素数量
TArray<FHitResult> hits = {}; ECollisionChannel channel(ECC_GameTraceChannel1); FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner()); GetWorld()->LineTraceMultiByChannel( OUT hits, camWorldLocation, end, channel, TraceParams ); DrawDebugLine(GetWorld(), camWorldLocation, end, FColor::Green, false, 2.0f); if (!hits.IsEmpty()) { // 替换sizeof(hits)为Num(),获取数组实际元素个数 for (int i = 0; i < hits.Num(); i++) { if (hits[i].GetActor() != nullptr) { UE_LOG(LogTemp, Error, TEXT("Line trace has hit: %s"), *(hits[i].GetActor()->GetName())); } } }
方案2:使用范围for循环(更简洁安全)
Unreal支持C++11及以上的范围for循环,可直接遍历数组元素,彻底避免手动索引出错:
TArray<FHitResult> hits = {}; ECollisionChannel channel(ECC_GameTraceChannel1); FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner()); GetWorld()->LineTraceMultiByChannel( OUT hits, camWorldLocation, end, channel, TraceParams ); DrawDebugLine(GetWorld(), camWorldLocation, end, FColor::Green, false, 2.0f); // 直接遍历每个命中结果,无需手动判断数组是否为空 for (const auto& Hit : hits) { if (Hit.GetActor() != nullptr) { UE_LOG(LogTemp, Error, TEXT("Line trace has hit: %s"), *(Hit.GetActor()->GetName())); } }
额外优化说明
- 移除了多余的
&hits[i] != nullptr判断:TArray在有效索引范围内的元素都是合法对象,无需检查指针是否为空。 - 范围for循环无需提前判断数组是否为空,空数组会直接跳过循环,代码更简洁高效。
内容的提问来源于stack exchange,提问作者zyrg
相关产品推荐
相关产品推荐

