FHitResult:Location 和 ImpactPoint
在上一篇文章中,我们已经添加了抓取组件。在这一篇文章中,我们了解一下抓取的点如何获取。
我们先回顾一下之前的扫掠检测实现,如代码清单 1 所示,通过调用 SweepSingleByChannel 函数实现。如果发生碰撞,则可以进一步使用 FHitResult 里面的碰撞信息。
- void UGrabber::Grab()
- {
- FVector Start = GetComponentLocation();
- FVector End = Start + GetForwardVector() * MaxGrabDistance;
- DrawDebugLine(GetWorld(), Start, End, FColor::Red);
- FCollisionShape Sphere = FCollisionShape::MakeSphere(GrabRadius);
- FHitResult HitResult;
- bool HasHit = GetWorld()->SweepSingleByChannel(HitResult,
- Start, End,
- FQuat::Identity,
- ECC_GameTraceChannel2,
- Sphere);
- if (HasHit)
- {
- AActor* HitActor = HitResult.GetActor();
- UE_LOG(LogTemp, Display, TEXT("Hit actor: %s"), *HitActor->GetActorNameOrLabel());
- }
- else
- {
- UE_LOG(LogTemp, Display, TEXT("No actor hit"));
- }
- }
我们可以把发生碰撞的点当成抓取的点。查看 FHitResult 官方文档,通过成员名字,我们猜测 Location 或 ImpactPoint 成员是我们想要的。
根据官方的定义:
FHitResult.Location 是指在碰撞检测时,运动形状(此处是球体)最终停留的位置。即如果发生碰撞,运动形状在世界空间中停留的位置。
FHitResult.ImpactPoint 是指运动形状与目标物体实际接触的点。即碰撞发生时的接触点。
上述介绍可能看着还不够直观,我们可以可视化一下。如代码清单 2 所示,我们通过 DrawDebugSphere() 函数绘制发生碰撞时的 Location 和 ImpactPoint 的位置。
- void UGrabber::Grab()
- {
- FVector Start = GetComponentLocation();
- FVector End = Start + GetForwardVector() * MaxGrabDistance;
- DrawDebugLine(GetWorld(), Start, End, FColor::Red);
- DrawDebugSphere(GetWorld(), End, 10, 10, FColor::Blue, true);
- FCollisionShape Sphere = FCollisionShape::MakeSphere(GrabRadius);
- FHitResult HitResult;
- bool HasHit = GetWorld()->SweepSingleByChannel(HitResult,
- Start, End,
- FQuat::Identity,
- ECC_GameTraceChannel2,
- Sphere);
- if (HasHit)
- {
- DrawDebugSphere(GetWorld(), HitResult.Location, 10, 10, FColor::Green, true);
- DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10, 10, FColor::Red, true);
- AActor* HitActor = HitResult.GetActor();
- UE_LOG(LogTemp, Display, TEXT("Hit actor: %s"), *HitActor->GetActorNameOrLabel());
- }
- else
- {
- UE_LOG(LogTemp, Display, TEXT("No actor hit"));
- }
- }
我们之前使用过 DrawDebugLine() 函数。DrawDebugSphere() 和它一样也是绘制调试函数,不过画的是球体。其函数定义如下:
- void DrawDebugSphere(const UWorld* InWorld,
- FVector const& Center,
- float Radius,
- int32 Segments,
- FColor const& Color,
- bool bPersistentLines = false,
- float LifeTime = -1.f,
- uint8 DepthPriority = 0,
- float Thickness = 0.f);
此处我们把 bPersistentLines 参数设置为 true,方便调试查看。
运行程序,可视化的结果如图 1 所示,绿色是 FHitResult.Location,红色是 FHitResult.ImpactPoint。可以看到 ImpactPoint 是我们平常理解的碰撞点;而此处 Location 是发生碰撞时,扫掠球体中心点所在的地方,因为球体是有体积的。
