UEC++学习(十)武器添加开火特效

目录

枪口特效

(1)单发枪

(2)连发枪

弹道特效

击中特效


枪口特效

(1)单发枪

在武器类中添加NiagaraSystem和NiagaraComponent组件两个变量,

	class UNiagaraSystem;
    class UNiagaraComponent;

    //枪口特效
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		UNiagaraSystem* MuzzleFX;

	//返回枪口特效组件
	UNiagaraComponent* SpawnMuzzleFX();

在Cpp中

UNiagaraFunctionLibrary::SpawnSystemAttached()

#include "NiagaraFunctionLibrary.h"
#include "NiagaraComponent.h"


UNiagaraComponent* ASTUBaseWeapon::SpawnMuzzleFX()
{
	//在枪口生成特效
    //WeaponMesh是武器骨骼网格体
	return UNiagaraFunctionLibrary::SpawnSystemAttached
	(
		MuzzleFX,
		WeaponMesh,
		"MuzzleFlashSocket",
		FVector::ZeroVector,
		FRotator::ZeroRotator,
		EAttachLocation::SnapToTarget,
		true
	);
}

(2)连发枪

在头文件中

class UNiagaraComponent;

	
    UPROPERTY()
		UNiagaraComponent* MuzzleFXComponent;

	void InitMuzzleFX();
	void SetMuzzleFXVisibility(bool Visible);

在CPP中

SetPaused():停止

SetVisibility():可见

#include "NiagaraComponent.h"

void ASTURifleWeapon::InitMuzzleFX()
{
	
    //这个SpawnMuzzleFX在上面单发枪基类实现的
	MuzzleFXComponent = SpawnMuzzleFX();
	SetMuzzleFXVisibility(true);
}

void ASTURifleWeapon::SetMuzzleFXVisibility(bool Visible)
{
	if (MuzzleFXComponent)
	{
		MuzzleFXComponent->SetPaused(!Visible);
		MuzzleFXComponent->SetVisibility(Visible, true);
	}
}

然后在开枪时激活,停止时关闭

void ASTURifleWeapon::Fire()
{
	InitMuzzleFX();
	GetWorldTimerManager().SetTimer(FireTimerHandle, this, &ASTURifleWeapon::MakeShot, TimerBetweenShots, true);
}

void ASTURifleWeapon::StopFire()
{
	GetWorldTimerManager().ClearTimer(FireTimerHandle);
	SetMuzzleFXVisibility(false);
}

弹道特效

在武器头文件中

    class UNiagaraComponent;
    class UNiagaraSystem;	

    
    //弹道特效
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		UNiagaraSystem* TraceFX;
    //这个TraceTargetName 是Niagara特效中的变量名
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		FString TraceTargetName = "TraceTarget";


    void SpawnTraceFX(const FVector& TraceStart, const FVector& TraceEnd);

在CPP中

其中的一些函数实现在C++学习(六)中可以找到

主要是将射线检测到的落点作为弹道特效的落点

UNiagaraFunctionLibrary::SpawnSystemAtLocation():生成特效

SetNiagaraVariableVec3():

#include "NiagaraComponent.h"
#include "NiagaraFunctionLibrary.h"


void ASTURifleWeapon::MakeShot()
{
	if (!GetWorld() || IsAmmoEmpty())
	{
		StopFire();
		return;
	}


	FVector TraceStart, TraceEnd;
	if (!GetTraceData(TraceStart, TraceEnd))
	{
		StopFire();
		return;
	}

	//通过摄像机的旋转来检测
	FHitResult HitResult;
	MakeHit(HitResult, TraceStart, TraceEnd);

	//弹道特效落点
	FVector TraceFXEnd = TraceEnd;

	//有检测到
	if (HitResult.bBlockingHit)
	{	
		TraceFXEnd = HitResult.ImpactPoint;	
		MakeDamage(HitResult);
		//击中特效
		WeaponFXComponent->PlayImpactFX(HitResult);

		绘制一条枪口到检测点的射线
		绘制调试射线 参数:World,开始位置,结束位置,颜色,判断射线是否永久绘制(默认false),存在时间,绘制深度的顺序,粗细 
		//DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), HitResult.ImpactPoint, FColor::Red, false, 3.0f, 0, 3.0f);

		绘制球形调试
		//DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.0f, 24, FColor::Red, false, 3.0f);

	}
	//else
	//{
	//	//绘制一条枪口到终点的射线
	//	//绘制调试射线 参数:World,开始位置,结束位置,颜色,判断射线是否永久绘制(默认false),存在时间,绘制深度的顺序,粗细 
	//	DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), TraceEnd, FColor::Red, false, 3.0f, 0, 3.0f);
	//}

    //弹道特效
	SpawnTraceFX(GetMuzzleWorldLocation(), TraceFXEnd);

	DecreaseAmmo();
}





void ASTURifleWeapon::SpawnTraceFX(const FVector& TraceStart, const FVector& TraceEnd)
{
	
	UNiagaraComponent* TraceFXComponent = UNiagaraFunctionLibrary::SpawnSystemAtLocation(GetWorld(), TraceFX, TraceStart);
	if (TraceFXComponent)
	{
		TraceFXComponent->SetNiagaraVariableVec3(TraceTargetName, TraceEnd);
	}
}

击中特效

这里是用ActorComponent来专门处理击中特效逻辑的,然后在落点生成贴花

在组件类中创建两个结构体用于存储不同的击中特效,这里是通过材质来判断击中的物体

在头文件中:

class UMaterialInterface;
class UNiagaraSystem;

//贴花
USTRUCT(BlueprintType)
struct FDecalData
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		UMaterialInterface* Material;
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		FVector Size = FVector(10.0f);
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		float LifeTime = 5.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		float FadeOutTime = 0.7f;
};

//粒子特效
USTRUCT(BlueprintType)
struct FImpactData
{
	GENERATED_USTRUCT_BODY();

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		UNiagaraSystem* NiagaraEffect;
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		FDecalData DecalData;

};

 
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		FImpactData DefaultImpactData;
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "VFX")
		TMap<UPhysicalMaterial*, FImpactData> ImpactDataMap;


	void PlayImpactFX(const FHitResult& Hit);

在CPP中:

UNiagaraFunctionLibrary::SpawnSystemAtLocation:生成特效

UGameplayStatics::SpawnDecalAtLocation:生成贴花

SetFadeOut():贴花消失

#include "NiagaraFunctionLibrary.h"
#include "PhysicalMaterials/PhysicalMaterial.h"
#include "Kismet/GameplayStatics.h"
#include "Components/DecalComponent.h"


void USTUWeaponFXComponent::PlayImpactFX(const FHitResult& Hit)
{
	FImpactData ImpactData = DefaultImpactData;

	//根据击中的不用材质 播放不同的特效
	//如果是根据材质的话,被击中的碰撞体需要开启bReturnPhysicalMaterial为true
	if (Hit.PhysMaterial.IsValid())
	{
		const UPhysicalMaterial* PhysMat = Hit.PhysMaterial.Get();
		if (ImpactDataMap.Contains(PhysMat))
		{
			ImpactData = ImpactDataMap[PhysMat];
		}
	}
	//niagara
	UNiagaraFunctionLibrary::SpawnSystemAtLocation(GetWorld(),
		ImpactData.NiagaraEffect,
		Hit.ImpactPoint,
		Hit.ImpactNormal.Rotation()
	);
		

	//decal
	UDecalComponent* DecalComponent = UGameplayStatics::SpawnDecalAtLocation(
		GetWorld(),
		ImpactData.DecalData.Material,
		ImpactData.DecalData.Size,
		Hit.ImpactPoint,
		Hit.ImpactNormal.Rotation()
	);

	if (DecalComponent)
	{
		DecalComponent->SetFadeOut(ImpactData.DecalData.LifeTime, ImpactData.DecalData.FadeOutTime);
	}
}

这里使用到的材质 是在碰撞设置中重载的

然后在武器类中添加这个组件类,

class USTUWeaponFXComponent;


	//击中特效
	UPROPERTY(VisibleAnywhere, Category = "VFX")
		USTUWeaponFXComponent* WeaponFXComponent;

在射击逻辑中调用组件的PlayImpactFX函数,将射线检测到的HitResult传递过去

void ASTURifleWeapon::MakeShot()
{
	if (!GetWorld() || IsAmmoEmpty())
	{
		StopFire();
		return;
	}


	FVector TraceStart, TraceEnd;
	if (!GetTraceData(TraceStart, TraceEnd))
	{
		StopFire();
		return;
	}

	//通过摄像机的旋转来检测
	FHitResult HitResult;
	MakeHit(HitResult, TraceStart, TraceEnd);

	//弹道特效落点
	FVector TraceFXEnd = TraceEnd;

	//有检测到
	if (HitResult.bBlockingHit)
	{	
		TraceFXEnd = HitResult.ImpactPoint;	
		MakeDamage(HitResult);
		//击中特效
		WeaponFXComponent->PlayImpactFX(HitResult);

		绘制一条枪口到检测点的射线
		绘制调试射线 参数:World,开始位置,结束位置,颜色,判断射线是否永久绘制(默认false),存在时间,绘制深度的顺序,粗细 
		//DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), HitResult.ImpactPoint, FColor::Red, false, 3.0f, 0, 3.0f);

		绘制球形调试
		//DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.0f, 24, FColor::Red, false, 3.0f);

	}
	//else
	//{
	//	//绘制一条枪口到终点的射线
	//	//绘制调试射线 参数:World,开始位置,结束位置,颜色,判断射线是否永久绘制(默认false),存在时间,绘制深度的顺序,粗细 
	//	DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), TraceEnd, FColor::Red, false, 3.0f, 0, 3.0f);
	//}

	//弹道特效
	SpawnTraceFX(GetMuzzleWorldLocation(), TraceFXEnd);

	DecreaseAmmo();
}

最终效果:

地上的弹孔就是用贴花做的

子弹特效

需要在构建文件中加入这两个模块

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值