首先我们有一个以character为基类的角色类AShooterCharacter。角色类中已有一个FireWeapon函数实现在游戏内开火。这个函数在每次按下鼠标左键时会被调用一次,类似于半自动步枪。接下来要实现按住开火,松开停火。
最快速简单的实现如下
//在SetupPlayerInputComponent内绑定
PlayerInputComponent->BindAction("FireButton", IE_Pressed, this, &AShooterCharacter::FireButtonPressed);
PlayerInputComponent->BindAction("FireButton", IE_Released, this, &AShooterCharacter::FireButtonReleased);
//在AShooterCharacter.h内定义 FTimerHandle类AutoFireTimer和射击间隔AutomaticFireRate
void AShooterCharacter::FireButtonPressed()
{ //设置Timer循环调用FireWeapon
GetWorldTimerManager().SetTimer(AutoFireTimer, this,
&AShooterCharacter::FireWeapon,AutomaticFireRate,true);
}
void AShooterCharacter::FireButtonReleased()
{ //清空AutoFireTimer设定的Timer
GetWorldTimerManager().ClearTimer(AutoFireTimer);
}
这个方法利用UE4的Timer功能实现自动按一定间隔循环开枪直至松开左键。但是实际游戏中存在着各种角色无法开枪的可能,例如死亡,子弹耗尽,收到某些效果射速改变或不让开枪。上面的方法即不利于实现上述的效果也不方便由蓝图去操作。所以应设置一个布尔变量bShouldFire表示是否能继续开枪,再定义一个布尔变量bFireButtonPressed检测鼠标左键状态,两者共同决定是否开枪。
//在SetupPlayerInputComponent内绑定
PlayerInputComponent->BindAction("FireButton", IE_Pressed, this, &AShooterCharacter::FireButtonPressed);
PlayerInputComponent->BindAction("FireButton", IE_Released, this, &AShooterCharacter::FireButtonReleased);
void AShooterCharacter::FireButtonPressed()
{
bFireButtonPressed = true;
StartFireTimer();
}
void AShooterCharacter::FireButtonReleased()
{
bFireButtonPressed = false;
}
void AShooterCharacter::StartFireTimer()
{
if (bShouldFire)
{
FireWeapon();
bShouldFire = false;
GetWorldTimerManager().SetTimer(AutoFireTimer, this,
&AShooterCharacter::AutoFireReset,AutomaticFireRate);
}
}
void AShooterCharacter::AutoFireReset()
{
bShouldFire = true;
if (bFireButtonPressed)
{
StartFireTimer();
}
}
StartFireTimer()和AutoFireReset()相互调用来实现循环开枪,只用修改bShouldFire就能阻止角色继续开火,而不是调用GetWorldTimerManager().ClearTimer(AutoFireTimer)来使角色停火。例如玩家开枪时枪射速变慢,原本要先ClearTimer再SetTimer,现在只用修改AutomaticFireRate的值即可,对外部蓝图实现效果也更方便。