You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 00:24:16