AddActorLocalRotation()

目前我们的坦克已经可以前后移动了。在这一篇文章中,我们继续添加左右转向的功能。

之前的移动功能,是使用 AddActorLocalOffset() 函数实现的。也有类似的旋转函数,为 AddActorLocalRotation(),它的原型如下:

  • void AddActorLocalRotation(FRotator DeltaRotation,
  •     bool bSweep=false,
  •     FHitResult* OutSweepHitResult=nullptr,
  •     ETeleportType Teleport = ETeleportType::None);

AddActorLocalRotation 的参数和 AddActorLocalOffset 也类似,只不过使用 DeltaRotation 参数指定角度。同样,bSweep 指定是否进行碰撞检测;OutSweepHitResult 指定发生碰撞时的碰撞信息;Teleport 指定旋转的移动方式。

在之前的 《AddActorLocalOffset()》 文章中,我们移动没有开启碰撞检测。现在我们需要移动和旋转都开启碰撞检测,所以来到坦克蓝图中,选择其根组件,是一个胶囊碰撞体。

如图 1 所示,我们修改细节窗体中的 碰撞 - 碰撞预设,将其修改为 BlockAllDynamic。接着我们调节一下坦克的 Mesh,让胶囊体底部不要超出,否则会碰撞到地面,导致无法控制坦克。

注意,初始摆放时,如果胶囊体碰到地面的话,就会触发碰撞,导致坦克无法移动。

图1 碰撞预设

设置好碰撞之后,我们开始实现左右转向功能。如代码清单 1 所示,我们定义 TurnRate 成员变量指定转向速度,并根据帧率计算旋转的角度,最终通过 AddActorLocalRotation() 设置旋转增量。

代码清单 1 旋转
  1. void ATank::Turn(float Value)
  2. {
  3.     FRotator DeltaRotation = FRotator::ZeroRotator;
  4.     DeltaRotation.Yaw = Value * TurnRate * UGameplayStatics::GetWorldDeltaSeconds(this);
  5.     AddActorLocalRotation(DeltaRotation, true);
  6. }

转向操作绑定的方式和移动一样,如代码清单 2 所示,使用 BindAxis() 函数设置。

代码清单 2 绑定
  1. void ATank::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
  2. {
  3.     Super::SetupPlayerInputComponent(PlayerInputComponent);
  4.  
  5.     PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &ATank::Move);
  6.     PlayerInputComponent->BindAxis(TEXT("Turn"), this, &ATank::Turn);
  7. }

最终的效果如以下视频所示,可以看到旋转正常,碰撞也正常。