BlueprintCallable

在上一篇文章中,我们已经实现了抓取事件的逻辑,是用蓝图实现的。在按键按下时,需要触发扫掠检测,这部分逻辑我们已经在 C++ 侧的 Grabber 场景组件里实现了。所以在本篇文章中,我们学习如何在蓝图里调用自己写的 C++ 函数。

交互的方法非常简单。如代码清单 1 所示,我们只需要对想要暴露的函数添加 UFUNCTION(BlueprintCallable) 宏即可。此处我们新增了两个函数 Grab 和 Release,用于蓝图调用。

代码清单 1 BlueprintCallable
  1. class CRYPTRAIDER_API UGrabber : public USceneComponent
  2. {
  3. public:
  4.     UFUNCTION(BlueprintCallable)
  5.     void Grab();
  6.  
  7.     UFUNCTION(BlueprintCallable)
  8.     void Release();
  9. };

Grab 和 Release 函数的具体实现,如代码清单 2 所示:Grab 函数里面的逻辑就是复制的之前在 TickComponent 函数里实现的扫掠检测逻辑;Release 函数里面目前仅是日志打印。

代码清单 2 实现
  1. void UGrabber::Grab()
  2. {
  3.     FVector Start = GetComponentLocation();
  4.     FVector End = Start + GetForwardVector() * MaxGrabDistance;
  5.  
  6.     DrawDebugLine(GetWorld(), Start, End, FColor::Red);
  7.  
  8.     FCollisionShape Sphere = FCollisionShape::MakeSphere(GrabRadius);
  9.     FHitResult HitResult;
  10.     bool HasHit = GetWorld()->SweepSingleByChannel(HitResult,
  11.         Start, End,
  12.         FQuat::Identity,
  13.         ECC_GameTraceChannel2,
  14.         Sphere);
  15.  
  16.     if (HasHit)
  17.     {
  18.         AActor* HitActor = HitResult.GetActor();
  19.         UE_LOG(LogTemp, Display, TEXT("Hit actor: %s"), *HitActor->GetActorNameOrLabel());
  20.     }
  21.     else
  22.     {
  23.         UE_LOG(LogTemp, Display, TEXT("No actor hit"));
  24.     }
  25. }
  26.  
  27. void UGrabber::Release()
  28. {
  29.     UE_LOG(LogTemp, Display, TEXT("Released grabber"))
  30. }

在蓝图中的使用方式,如图 1 所示,因为调用的是类成员函数,所以我们需要指定类的“this 指针”。 Grabber 类可以从左侧组件标签卡中拖拽得到。

图1 蓝图

运行程序。尝试在视线里没有雕塑时按下鼠标左键,以及视线里有雕塑时按下鼠标左键。如图 2 所示,可以看到在控制台中打印了预期的日志。

即时编译后,如果运行报错,可以尝试重新编译蓝图。如果还不行,就退出编辑器,重新编译 C++ 项目。

图2 运行