实现炮塔类

在这篇文章中,我们准备实现炮塔类。我们先实现以下功能:让炮塔能够自动追踪玩家坦克,为后续开火做准备。

我们的坦克和炮塔都需要派生自实现的 BasePawn 类。之前我们已经实现了坦克类。创建的方式是在 BasePawn C++ 类上右击选择 创建派生自BasePawn的C++类

这次我们尝试一种新的方法。我们选择菜单 工具 - 新建C++类,如图 1 所示,我们在“所有类”标签卡下,搜索到 BasePawn 类进行创建。我们将炮塔类命名为 Tower。

图1 新建派生类

创建好炮塔类之后,我们开始实现代码。因为我们需要追踪玩家坦克,所以必须先获取到坦克这个对象。

如代码清单 1 所示,我们将玩家坦克的获取放在 BeginPlay() 时机,并通过 UGameplayStatics::GetPlayerPawn() 函数获取到玩家类。注意需要使用 Cast 转成具体的子类。

代码清单 1 GetPlayerPawn
  1. // Called when the game starts or when spawned
  2. void ATower::BeginPlay()
  3. {
  4.     Super::BeginPlay();
  5.  
  6.     Tank = Cast<ATank>(UGameplayStatics::GetPlayerPawn(this, 0));
  7. }

接着我们就可以实现炮塔的追踪了。我们把追踪逻辑放在 Tick() 中,逐帧检测。我们只在一定范围内进行追踪,所以我们设置一个变量 FireRange 指定追踪范围,并暴露给蓝图。

然后使用 FVector::Dist() 函数计算炮塔和坦克的距离。如果在追踪范围内,我们就使用 RotateTurret 函数旋转头部。

RotateTurret 函数我们已经在上一篇文章 《旋转炮塔》 里实现好了,输入是看向的对象,此处我们将其指定为坦克。

代码清单 2 RotateTurret
  1. // Called every frame
  2. void ATower::Tick(float DeltaTime)
  3. {
  4.     Super::Tick(DeltaTime);
  5.  
  6.     // Find the distance to the Tank
  7.     if (Tank)
  8.     {
  9.         float Distance = FVector::Dist(GetActorLocation(), Tank->GetActorLocation());
  10.  
  11.         // Check to see if the Tank is in range
  12.         if (Distance <= FireRange)
  13.         {
  14.             // If in range, rotate turret toward Tank
  15.             RotateTurret(Tank->GetActorLocation());
  16.         }
  17.     }
  18. }

原先的炮塔蓝图,我们是基于 BasePawn 创建的。现在我们需要将其变成基于 Tower。我们不需要从头开始创建,只需要如图 2 所示,打开之前炮塔蓝图的 类设置,将 父类 参数设置为 Tower。

图2 设置父类

最终的效果如下方视频所示,可以看到玩家坦克接近炮塔时,炮塔齐刷刷指向了坦克。