实现炮塔类
在这篇文章中,我们准备实现炮塔类。我们先实现以下功能:让炮塔能够自动追踪玩家坦克,为后续开火做准备。
我们的坦克和炮塔都需要派生自实现的 BasePawn 类。之前我们已经实现了坦克类。创建的方式是在 BasePawn C++ 类上右击选择 创建派生自BasePawn的C++类。
这次我们尝试一种新的方法。我们选择菜单 工具 - 新建C++类,如图 1 所示,我们在“所有类”标签卡下,搜索到 BasePawn 类进行创建。我们将炮塔类命名为 Tower。
创建好炮塔类之后,我们开始实现代码。因为我们需要追踪玩家坦克,所以必须先获取到坦克这个对象。
如代码清单 1 所示,我们将玩家坦克的获取放在 BeginPlay() 时机,并通过 UGameplayStatics::GetPlayerPawn() 函数获取到玩家类。注意需要使用 Cast 转成具体的子类。
- // Called when the game starts or when spawned
- void ATower::BeginPlay()
- {
- Super::BeginPlay();
- Tank = Cast<ATank>(UGameplayStatics::GetPlayerPawn(this, 0));
- }
接着我们就可以实现炮塔的追踪了。我们把追踪逻辑放在 Tick() 中,逐帧检测。我们只在一定范围内进行追踪,所以我们设置一个变量 FireRange 指定追踪范围,并暴露给蓝图。
然后使用 FVector::Dist() 函数计算炮塔和坦克的距离。如果在追踪范围内,我们就使用 RotateTurret 函数旋转头部。
RotateTurret 函数我们已经在上一篇文章 《旋转炮塔》 里实现好了,输入是看向的对象,此处我们将其指定为坦克。
- // Called every frame
- void ATower::Tick(float DeltaTime)
- {
- Super::Tick(DeltaTime);
- // Find the distance to the Tank
- if (Tank)
- {
- float Distance = FVector::Dist(GetActorLocation(), Tank->GetActorLocation());
- // Check to see if the Tank is in range
- if (Distance <= FireRange)
- {
- // If in range, rotate turret toward Tank
- RotateTurret(Tank->GetActorLocation());
- }
- }
- }
原先的炮塔蓝图,我们是基于 BasePawn 创建的。现在我们需要将其变成基于 Tower。我们不需要从头开始创建,只需要如图 2 所示,打开之前炮塔蓝图的 类设置,将 父类 参数设置为 Tower。
最终的效果如下方视频所示,可以看到玩家坦克接近炮塔时,炮塔齐刷刷指向了坦克。