12uec++多人游戏【自定义碰撞通道+头部暴击+连续开火】

新建一个对象通道 

 打开CoopGame.h,添加一个值

#define COLLISION_WEAPON ECC_GameTraceChannel1

然后在fire函数的该弹道函数里换上该参数

 

 ======================================

给武器类添加一个基础伤害成员变量

	//基础伤害
	UPROPERTY(EditDefaultsOnly, Category = "Weapon")
	float BaseDamage;

在构造函数中,初始化

BaseDamage = 20;

继续完善一下fire函数

void ASWeapen::Fire()
{
	//创建一个撞击句柄,用来获取弹道相关信息
	FHitResult Hit;
	//弹道的起点,我们设置为角色眼睛的位置
	AActor * MyOwner = GetOwner();
	if (MyOwner)
	{	//位置
		FVector EyeLocation;
		//方向
		FRotator EyeRotator;
		//得到眼睛的位置和角度
		MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotator);
		//弹道的终点就是起点+方向*10000
		FVector TraceEnd = EyeLocation + (EyeRotator.Vector() * 1000);
		//弹道特效的结束点
		FVector TraceEndPoint = TraceEnd;
		//设置碰撞通道为可见性通道
		FCollisionQueryParams  QueryParams;
		//让射线忽略玩家和枪
		QueryParams.AddIgnoredActor(MyOwner);
		QueryParams.AddIgnoredActor(this);
		//符合追踪设为true,可以让射击更加精准
		QueryParams.bTraceComplex = true;
		//返回命中目标的表面材质
		QueryParams.bReturnPhysicalMaterial = true;


		//在创建一个单轨迹线来计算弹道
		//LineTraceSingleByChannel击中物体返回true
		if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, COLLISION_WEAPON, QueryParams))
		{
			//命中对象
			AActor * HitActor = Hit.GetActor();
			//实际的伤害
			float ActualDamage = BaseDamage;
			//得到命中物体表面材质
			EPhysicalSurface SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());
			//如果命中的是头部表面材质,伤害变成四倍
			if (SurfaceType == SURFACE_FLESHVULNERABLE)
			{
				ActualDamage *= 4;
			}

			//调用伤害函数
			//参数分别为伤害对象、基础伤害、设计方向、命中信息(命中句柄)、MyOwner->GetInstigatorController(暂时不了解)
			//this(伤害者) 和伤害类型 
			UGameplayStatics::ApplyPointDamage(HitActor, ActualDamage, EyeRotator.Vector(), Hit, MyOwner->GetInstigatorController(), this, DamageType);

			//根据材质的不同,进行不同的处理
			UParticleSystem * SelectedEffect = nullptr;
			switch (SurfaceType)
			{
				//这两种情况是一个效果
			case SURFACE_FLESHDEFAULT:
			case SURFACE_FLESHVULNERABLE:
				SelectedEffect = FleshImpactEffect;
				break;
			default:
				SelectedEffect = DefaultImpactEffect;
				break;

			}

			//生成特效在命中点
			//ImpactEffect:特效 ImpactPoint:打击点 Rotation():打击方向
			if (SelectedEffect)
			{
				UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
			}
			//命中的时候,修改弹道特效的终点
			TraceEndPoint = Hit.ImpactPoint;



		}
		//方便debug
		DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::Red, false, 1, 0, 1);
		//射击特效
		PlayFireEffects(TraceEndPoint);
	}

}

为了验证,其伤害效果,我们在靶子的蓝图编辑事件

 测试

 

 ====================================

武器类里面声明两个函数 

	//开始射击函数
	void StartFire();
	//停止设计函数
	void StoptFire();

再声明几个变量

	//计时器句柄
	FTimerHandle TimerHandle_TimeBetweenShots;
	//上次开火时间点
	float FireLastTime;
	//开火的频率,每分钟多少枪
	UPROPERTY(EditDefaultsOnly, Category = "Weapon")
	float RateOfFire;
	//开火的间隔时间
	float TimeBetweenShots;

在构造函数中初始化RateOfFire

RateOfFire = 600;

然后在游戏开始函数里,算得开火间隔

// Called when the game starts or when spawned
void ASWeapen::BeginPlay()
{
	Super::BeginPlay();
	TimeBetweenShots = 60 / RateOfFire;
}

 在fire函数的最下面,记录最后开火的时间

void ASWeapen::Fire()
{
	//创建一个撞击句柄,用来获取弹道相关信息
	FHitResult Hit;
	//弹道的起点,我们设置为角色眼睛的位置
	AActor * MyOwner = GetOwner();
	if (MyOwner)
	{	//位置
		FVector EyeLocation;
		//方向
		FRotator EyeRotator;
		//得到眼睛的位置和角度
		MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotator);
		//弹道的终点就是起点+方向*10000
		FVector TraceEnd = EyeLocation + (EyeRotator.Vector() * 1000);
		//弹道特效的结束点
		FVector TraceEndPoint = TraceEnd;
		//设置碰撞通道为可见性通道
		FCollisionQueryParams  QueryParams;
		//让射线忽略玩家和枪
		QueryParams.AddIgnoredActor(MyOwner);
		QueryParams.AddIgnoredActor(this);
		//符合追踪设为true,可以让射击更加精准
		QueryParams.bTraceComplex = true;
		//返回命中目标的表面材质
		QueryParams.bReturnPhysicalMaterial = true;


		//在创建一个单轨迹线来计算弹道
		//LineTraceSingleByChannel击中物体返回true
		if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, COLLISION_WEAPON, QueryParams))
		{
			//命中对象
			AActor * HitActor = Hit.GetActor();
			//实际的伤害
			float ActualDamage = BaseDamage;
			//得到命中物体表面材质
			EPhysicalSurface SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());
			//如果命中的是头部表面材质,伤害变成四倍
			if (SurfaceType == SURFACE_FLESHVULNERABLE)
			{
				ActualDamage *= 4;
			}

			//调用伤害函数
			//参数分别为伤害对象、基础伤害、设计方向、命中信息(命中句柄)、MyOwner->GetInstigatorController(暂时不了解)
			//this(伤害者) 和伤害类型 
			UGameplayStatics::ApplyPointDamage(HitActor, ActualDamage, EyeRotator.Vector(), Hit, MyOwner->GetInstigatorController(), this, DamageType);

			//根据材质的不同,进行不同的处理
			UParticleSystem * SelectedEffect = nullptr;
			switch (SurfaceType)
			{
				//这两种情况是一个效果
			case SURFACE_FLESHDEFAULT:
			case SURFACE_FLESHVULNERABLE:
				SelectedEffect = FleshImpactEffect;
				break;
			default:
				SelectedEffect = DefaultImpactEffect;
				break;

			}

			//生成特效在命中点
			//ImpactEffect:特效 ImpactPoint:打击点 Rotation():打击方向
			if (SelectedEffect)
			{
				UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
			}
			//命中的时候,修改弹道特效的终点
			TraceEndPoint = Hit.ImpactPoint;



		}
		//方便debug
		DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::Red, false, 1, 0, 1);
		//射击特效
		PlayFireEffects(TraceEndPoint);
		//最后开火的时间
		FireLastTime = GetWorld()->TimeSeconds;
	}

}

实现这两个函数

void ASWeapen::StartFire()
{
	float FirstDelay = FMath::Max(0.0f, FireLastTime + TimeBetweenShots - GetWorld()->TimeSeconds);
	GetWorldTimerManager().SetTimer(TimerHandle_TimeBetweenShots, this, &ASWeapen::Fire, TimeBetweenShots, true, FirstDelay);
}

void ASWeapen::StoptFire()
{
	GetWorldTimerManager().ClearTimer(TimerHandle_TimeBetweenShots);
}

然后在玩家类里也声明两个函数

	//开始射击函数
	void StartFire();
	//停止设计函数
	void StoptFire();

之前的fire函数就不要了

然后定义函数

void ASCharacter::StartFire()
{
	if (CurrentWeapen1)
	{
		CurrentWeapen1->StartFire();
	}
}

void ASCharacter::StoptFire()
{
	if (CurrentWeapen1)
	{
		CurrentWeapen1->StoptFire();
	}
}

绑定开火

	//开火
	PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &ASCharacter::StartFire);
	PlayerInputComponent->BindAction("Fire", IE_Released, this, &ASCharacter::StoptFire);

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无情的阅读机器

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值