Ue4C++编程------伤害与c++(一)

    前面文中讲述了如何创建一个血条,本文将讲述如何创造伤害,怎么收到伤害。这在游戏中是相当重要的,因为大部分游戏都是有伤害机制的,当然,我们不会对伤害的数值进行研究,只进行简单的处理。

    首先在武器actor中,在构造玩collision时,设置为不碰撞,因为我们是只需要在挥剑的时候开启碰撞,其它时候应该是取消碰撞的。如下所示:

WeaponCollision->SetCollisionEnabled(ECollisionEnabled::NoCollision);

    接着在我们的人物character中,在挥剑的时候,开启碰撞,并设置一个定时器,在播放完蒙太奇的时候,才允许碰撞,因此首先,我们创建一个bool变量,用来控制OnHit函数,如下所示:

bool bCanAttack;
void ActiveAttack();
void DeActiveAttack(); // 不激活武器
void AWeaponActor::ActiveAttack()
{
	bCanAttack = true;
	if (WeaponCollision != nullptr) // 激活碰撞
	{
		WeaponCollision->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	}
}

void AWeaponActor::DeActiveAttack() // 关闭碰撞
{
	bCanAttack = false;
	if (WeaponCollision != nullptr)
	{
		WeaponCollision->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	}
}

    接着在我们的人物character中,当挥剑时激活武器。而在播放完蒙太奇后则不激活武器,如下所示:

void ABlogProjectCharacter::Attack()
{
	UHeroAnimInstance* AnimInstance = Cast<UHeroAnimInstance>(GetMesh()->GetAnimInstance());
	if (AnimInstance != nullptr)
	{
		if (!AnimInstance->Montage_IsPlaying(AttackMontage)) // 如果该蒙太奇动画未在播放,则进行播放
		{
			Weapon->ActiveAttack();
			float fDt = AnimInstance->Montage_Play(AttackMontage);
			FTimerHandle ActiveWeapon;
			GetWorld()->GetTimerManager().SetTimer(ActiveWeapon, [=]() {
				Weapon->DeActiveAttack();
			}, fDt, false);
		}
	}
}

    接着我们创建一个接口,该接口是为了在发生碰撞中,只有实现了该接口的actor,才是有效的碰撞,如下图所示:    

    在接口函数中,定义一个受到伤害的函数,如下所示:

class BLOGPROJECT_API IBeAttackInterface
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
	
	virtual void BeAttacked(float fDamage) = 0;
	
};

    显然,我们的AI需要继承这个接口,并实现这个纯虚函数。我们可以在这个函数中,对我们的生命值进行加减,从而更新我们的血量。但是,这里我介绍另一种方法。

    首先在AI类中,重写一个叫TakeDamage的方法。为什么使用这种方法呢,因为这个函数中有个伤害类型的字段,我们可以根据不同的伤害类型,来使我们的AI做出不同的表现,但这里我只是简单的更新我们的血量,只是说一个思路。如下所示:

virtual float TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
float AAIBlogCharacter::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	CurrentHealth -= Damage;
	if (CurrentHealth <= 0) // 受到足够的伤害了,销毁actor
	{
		Destroy();
	}

	return 0.0f;
}

注意,我们这个函数是虚函数,那应该怎么调用这个函数呢?其实是不用调用的,引擎已经帮我们做好了这些,只要我们调用applydamage,便会调用该回调函数,从而造成伤害。因此,在我们的武器类中,实现OnHIt函数,如下所示:

void AWeaponActor::OnHit(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("OnHit"));
	if (bCanAttack && OtherActor != this) // 在攻击有效时,造成伤害
	{
		IBeAttackInterface* AC = Cast<IBeAttackInterface>(OtherActor);
		if (AC != nullptr)
		{
			UGameplayStatics::ApplyDamage(OtherActor, 10.0f, nullptr, this, UDamageType::StaticClass()); // 造成10点伤害
		}
	}
}

    编译代码并测试成功,可以看到我们已经对AI造成了伤害。:

    




    

猜你喜欢

转载自blog.csdn.net/li2818/article/details/80917846