新建一个对象通道

打开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);