C# · 12月 19, 2021

UE4【C++】子弹伤害系统使用

可能很多初学者如果想知道UE4的这种伤害系统如何使用起来会有点迷茫。

我自己做了demo给大家参考下。

首先要有个子弹类。

.h代码如下

1 UCLASS()

2 class SNVRCLAYSHOOTING_API AProjectile : public AActor

3 {

4 GENERATED_BODY()

5

6 public:

7 // Sets default values for this actor's properties

8 AProjectile();

9

10 UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category = “Projectile”)

11 UStaticMeshComponent* ProjectileMesh;

12

13 UPROPERTY(VisibleAnywhere,Category = “Projectile”)

14 UParticleSystemComponent* LaunchParticle; //烟火,开枪时

15

16 UPROPERTY(VisibleAnywhere,Category = “Projectile”)

17 UProjectileMovementComponent *ProjectileMovementComponent = nullptr;

18

19 protected:

20 // Called when the game starts or when spawned

21 virtual void BeginPlay() override;

22

23 UFUNCTION()

24 void OnHit(UPrimitiveComponent* HitComponent,AActor* OtherActor,UPrimitiveComponent* OtherComp,FVector NormalImpulse,const FHitResult& Hit);

25

26 public:

27 // Called every frame

28 virtual void Tick(float DeltaTime) override;

29

30 UFUNCTION(BlueprintCallable,Category = “Projectile_Fun”)

31 void LaunchProjectile(FVector Speed);

32

33 };

View Code

.cpp代码如下

1 AProjectile::AProjectile()

2 {

3 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.

4 PrimaryActorTick.bCanEverTick = true;

5

6 ProjectileMovementComponent = CreateDefaultSubobject(FName(“ProjectileMovement”)); //生成组件

7 ProjectileMovementComponent->bAutoActivate = false; //自动飞行调成false

8

9 ProjectileMesh = CreateDefaultSubobject(FName(“ProjectileMesh”));

10 RootComponent = ProjectileMesh;

11 ProjectileMesh->SetNotifyRigidBodyCollision(true);

12 ProjectileMesh->SetVisibility(true);

13

14 LaunchParticle = CreateDefaultSubobject(FName(“LaunchParticle”));

15 LaunchParticle->SetupAttachment(ProjectileMesh); //将粒子效果绑定在根结点上(即ProjectileMesh)

16 LaunchParticle->SetAutoActivate(true); //创建好就启动

17

18 ProjectileMesh->OnComponentHit.AddDynamic(this,&AProjectile::OnHit);

19

20 InitialLifeSpan = 5.0f;

21 }

22

23 // Called when the game starts or when spawned

24 void AProjectile::BeginPlay()

25 {

26 Super::BeginPlay();

27

28 }

29

30 // Called every frame

31 void AProjectile::Tick(float DeltaTime)

32 {

33 Super::Tick(DeltaTime);

34

35 }

36 void AProjectile::LaunchProjectile(FVector Speed)

37 {

38 ProjectileMovementComponent->SetVeLocityInLocalSpace(Speed);

39 ProjectileMovementComponent->Activate(); //可以飞行了

40 }

41 //碰撞后发生的事件

42 void AProjectile::OnHit(UPrimitiveComponent* HitComponent,const FHitResult& Hit)

43 {

44 UE_LOG(LogTemp,Warning,TEXT(“AProjectile::OnHit–OtherActor.Name=%s”),*OtherActor->GetName()); //撞击后给个提示

45

46 ProjectileMesh->SetNotifyRigidBodyCollision(false); //碰撞之后再也不发生碰撞事件

47 //CollisionMesh->DestroyComponent(); //不是DestroyActor,Component是单一一个

48

49 //受伤害源OtherActor的TakeDamage()会被调用

50 UGameplayStatics::ApplyPointDamage(OtherActor,10.0f,GetActorLocation(),Hit,NULL,UDamageType::StaticClass());

51

52 Destroy();

53 }

View Code

伤害的入口从OnHit看出,调用了UGameplayStatics::ApplyPointDamage;

第一个参数就是受伤害源,UE4的伤害系统会调用受伤害源的TakeDamege接口;

此时子弹有了伤害力,那么受伤害源就要被伤害;

每个actor都有这个接口virtual float TakeDamage(float DamageAmount,struct FDamageEvent const& DamageEvent,class AController* EventInstigator,AActor* DamageCauser);

只要重写这个接口,写上自己的处理逻辑。

受伤害源部分代码如下:

1 float ADamagedActor::TakeDamage(float DamageAmount,AActor* DamageCauser)

2 {

3 float actuallyApplied = 0.0f;

4

5 MaxHP -= DamageAmount;

6

7 UE_LOG(LogTemp,TEXT(“ADamagedActor::TakeDamage–MaxHP=%f”),MaxHP);

8

9 actuallyApplied = FMath::Clamp(MaxHP,0.0f,100.0f);

10

11 return actuallyApplied;

12 }

View Code

以上就是简单的使用UE4的伤害系统。