首先新建一个派生自Actor的类
然后增加生命值组件,静态网格体组件,径向力组件,并全部向前声明
新建一个名为OnHealthChanged(生命值发生更改时)的函数,用于绑定我们的生命值组件
.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SExplosiveBarrel.generated.h"
class USHealthComponent;
class USHealthComponent;
class URadialForceComponent;
class UParticleSystem;
UCLASS()
class COOPGAME_API ASExplosiveBarrel : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASExplosiveBarrel();
protected:
UPROPERTY(VisibleAnywhere,Category="Components")//生命值组件
USHealthComponent* HealthComp;
UPROPERTY(VisibleAnywhere,Category="Components")//静态网格体组件
UStaticMeshComponent* MeshComp;
UPROPERTY(VisibleAnywhere,Category="Components")//径向力组件
URadialForceComponent* RadialForceComp;
UFUNCTION()
void OnHealthChanged(USHealthComponent* OwningHealthComp, float Health, float HealthDelta, const class UDamageType* DamageType,
class AController* InstigatedBy, AActor* DamageCauser);
//调用时进行复制
UPROPERTY(ReplicatedUsing = OnRep_Exploded)
//是否爆炸
bool bExploded;
UFUNCTION()
void OnRep_Exploded();
/*Impulse applied to the barrel mesh when it explodes to boost it up a litter*/
UPROPERTY(EditDefaultsOnly, Category = "FX")
float ExplosionImpulse;
/*Particle to play when health reached zero*/
UPROPERTY(EditDefaultsOnly, Category = "FX")
UParticleSystem* ExplosinEffect;
/*The material to replace the original on the mesh once exploded (a blackened version)*/
UPROPERTY(EditDefaultsOnly, Category = "FX")
UMaterialInterface* ExplodedMaterial;
//虚拟材质界面
};
.cpp
#include "SExplosiveBarrel.h"
#include "SHealthComponent.h"
#include "Kismet/GameplayStatics.h"
#include "PhysicsEngine/RadialForceComponent.h"
#include "Net/UnrealNetwork.h"
// Sets default values
ASExplosiveBarrel::ASExplosiveBarrel()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
HealthComp = CreateAbstractDefaultSubobject<USHealthComponent>(TEXT("Healthcomp"));
HealthComp->OnHealthChanged.AddDynamic(this, &ASExplosiveBarrel::OnHealthChanged);
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
MeshComp->SetSimulatePhysics(true);//将物理模拟设置为真
MeshComp->SetCollisionObjectType(ECC_PhysicsBody);//将碰撞对象类型设置为了物理实体,这一项的作用时,默认情况下RadialForceComponent仅会影响几条通道,而物理实体则是其中一条
RootComponent = MeshComp;
RadialForceComp = CreateDefaultSubobject<URadialForceComponent>(TEXT("RadialForceComp"));
RadialForceComp->SetupAttachment(MeshComp);//设置附加网格体
RadialForceComp->Radius = 250;//设置半径
RadialForceComp->bImpulseVelChange = true;//作用力速率变化为真
RadialForceComp->bAutoActivate = false;//Prevent component from ticking, and only use fireImpulse() instead //自动激活设为假
RadialForceComp->bIgnoreOwningActor = true;//是否忽略所属Actor设为真,这样才能忽略自身,自身的网格体,从而只对其它物体施加径向力
ExplosionImpulse = 400;
SetReplicates(true);
SetReplicateMovement(true);
}
void ASExplosiveBarrel::OnHealthChanged(USHealthComponent* OwningHealthComp, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{
if (bExploded)
{
//Nothing left to do already exploded.
return;
}
if (Health<=0.0f)//这一项主要检查我们的生命值是否低于或等于0
{
//Explode!
bExploded = true;
OnRep_Exploded();
//Boot the barrel upwards
FVector BoostIntensity = FVector::UpVector * ExplosionImpulse;//我们对网格体组件施加作用力,让其能向上弹起
MeshComp->AddImpulse(BoostIntensity, NAME_None, true);
RadialForceComp->FireImpulse();//触发RadialForceComponent以释放作用力
//@TODDO: Apply radial damage
}
}
void ASExplosiveBarrel::OnRep_Exploded()
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosinEffect, GetActorLocation());//ZX生成爆炸时粒子特效
MeshComp->SetMaterial(0, ExplodedMaterial);//设置为爆炸材质
}
void ASExplosiveBarrel::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps)const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ASExplosiveBarrel, bExploded);
}