P129_ Rocket Projectiles
P129_1 创建火箭

P129_2 创建火箭发射器

P129_3 初始化弹药

P129_4 禁止重复添加 CharacerOverlay

P130_ Rocket Trails
P131_Spawn Rocket Trails
- 如果把拖尾特效直接放在火箭蓝图作为组件,则火箭Destroy时其也会销毁.
- 本节需要注意的点就是对于产生爆炸的粒子特效,我们在服务端可以让CollisionBox发生碰撞以此来生成特效.但是伤害判断还是在Server上.
- 还有一点就是为了满足 Rocket 特有的生成特效的时机 , 我们 override了,父类Projectile父类的OnHit , Destroyed()方法 , 但是没有 Call Super的技巧.
P131_1 ProjectileRocket.h
#pragma once#include "CoreMinimal.h"
#include "Weapon/Projectile.h"
#include "ProjectileRocket.generated.h"UCLASS()
class BLASTER_API AProjectileRocket : public AProjectile
{GENERATED_BODY()public:#pragma region SystemAProjectileRocket();virtual void BeginPlay() override;virtual void Destroyed() override;virtual void OnHit(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor,UPrimitiveComponent* OtherComp,FVector NormalImpulse,const FHitResult& SweepResult) override;#pragma endregion#pragma region Componet UPROPERTY(VisibleAnywhere)class UStaticMeshComponent* RocketMesh;#pragma endregion#pragma region TrailUPROPERTY(EditAnywhere)class UNiagaraSystem* TrailSystem;UPROPERTY(EditAnywhere)class UNiagaraComponent* TrailSystemComponent;FTimerHandle DestroyTimer;void DestroyTimerFinished();UPROPERTY(EditAnywhere)float DestroyTime = 3.0f;#pragma endregion#pragma region SoundUPROPERTY(EditAnywhere)class USoundCue* ProjectileLoop;UPROPERTY()class UAudioComponent* ProjectileLoopComponent;UPROPERTY(EditAnywhere)class USoundAttenuation* LoopingSoundAttenuation;#pragma endregion
P131_2 Rocket Movement Component
#include "Weapon/ProjectileRocket.h"
#include "Kismet/GameplayStatics.h"
#include "NiagaraFunctionLibrary.h"
#include "Components/BoxComponent.h"
#include "Sound/SoundCue.h"
#include "NiagaraComponent.h"
#include "NiagaraSystemInstance.h"
#include "Components/AudioComponent.h"#pragma region SystemAProjectileRocket::AProjectileRocket()
{RocketMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RocketMesh"));RocketMesh->SetupAttachment(GetRootComponent());RocketMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);}void AProjectileRocket::BeginPlay()
{Super::BeginPlay();if (!HasAuthority()) { //Projectile Rocket 现在客户端也可以碰撞了,只不过我们只想在 服务端 处理伤害CollisionBox->OnComponentHit.AddDynamic(this,&AProjectileRocket::OnHit);}if (TrailSystem) {TrailSystemComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(TrailSystem,GetRootComponent(),FName(),GetActorLocation(),GetActorRotation(),EAttachLocation::KeepWorldPosition,false);}if (ProjectileLoop && LoopingSoundAttenuation) {ProjectileLoopComponent = UGameplayStatics::SpawnSoundAttached(ProjectileLoop,GetRootComponent(),FName(),GetActorLocation(),EAttachLocation::KeepWorldPosition,false,1.0f,1.0f,0.0f,LoopingSoundAttenuation,(USoundConcurrency*)nullptr,false //bAutoDestroy);}}void AProjectileRocket::Destroyed()
{}//Server & Client
void AProjectileRocket::OnHit(UPrimitiveComponent* HitComp,AActor* OtherActor,UPrimitiveComponent* OtherComp,FVector NormalImpulse,const FHitResult& SweepResult)
{APawn* FireingPawn = GetInstigator();//只在服务端处理伤害if (FireingPawn && HasAuthority()) {AController* FiringController = FireingPawn->GetController();if (FiringController) {UGameplayStatics::ApplyRadialDamageWithFalloff(this,Damage, //Base Damage10.0f, //MinimumDamageGetActorLocation(), //Origin Location200.0f, //Inner Radius500.0f, // Outer Radius1.0f, //LinearUDamageType::StaticClass(), //DamageTypeClassTArray<AActor*>(), //Ignore Arraythis, //Damage CauserFiringController //InsitigatorController);}}//Super::OnHit(HitComp, OtherActor, OtherComp, NormalImpulse, SweepResult);GetWorldTimerManager().SetTimer(DestroyTimer,this,&AProjectileRocket::DestroyTimerFinished,DestroyTime);if (ImpactParticles) {UGameplayStatics::SpawnEmitterAtLocation(GetWorld(),ImpactParticles,GetActorTransform());}if (ImpactSound) {UGameplayStatics::PlaySoundAtLocation(this, ImpactSound, GetActorLocation());}if (RocketMesh) {RocketMesh->SetVisibility(false);}if (CollisionBox) {CollisionBox->SetCollisionEnabled(ECollisionEnabled::NoCollision);}if (TrailSystemComponent) {TrailSystemComponent->GetSystemInstance()->Deactivate();}if (ProjectileLoopComponent && ProjectileLoopComponent->IsPlaying()) {ProjectileLoopComponent->Stop();}
}#pragma endregion#pragma region Trail
void AProjectileRocket::DestroyTimerFinished()
{Destroy();
}#pragma endregion
P132_ Rocket Movement Component