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


    新建一个对象通道 

     打开CoopGame.h,添加一个值

    #define COLLISION_WEAPON ECC_GameTraceChannel1

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

     

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

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

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

    在构造函数中,初始化

    BaseDamage = 20;

    继续完善一下fire函数

    1. void ASWeapen::Fire()
    2. {
    3. //创建一个撞击句柄,用来获取弹道相关信息
    4. FHitResult Hit;
    5. //弹道的起点,我们设置为角色眼睛的位置
    6. AActor * MyOwner = GetOwner();
    7. if (MyOwner)
    8. { //位置
    9. FVector EyeLocation;
    10. //方向
    11. FRotator EyeRotator;
    12. //得到眼睛的位置和角度
    13. MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotator);
    14. //弹道的终点就是起点+方向*10000
    15. FVector TraceEnd = EyeLocation + (EyeRotator.Vector() * 1000);
    16. //弹道特效的结束点
    17. FVector TraceEndPoint = TraceEnd;
    18. //设置碰撞通道为可见性通道
    19. FCollisionQueryParams QueryParams;
    20. //让射线忽略玩家和枪
    21. QueryParams.AddIgnoredActor(MyOwner);
    22. QueryParams.AddIgnoredActor(this);
    23. //符合追踪设为true,可以让射击更加精准
    24. QueryParams.bTraceComplex = true;
    25. //返回命中目标的表面材质
    26. QueryParams.bReturnPhysicalMaterial = true;
    27. //在创建一个单轨迹线来计算弹道
    28. //LineTraceSingleByChannel击中物体返回true
    29. if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, COLLISION_WEAPON, QueryParams))
    30. {
    31. //命中对象
    32. AActor * HitActor = Hit.GetActor();
    33. //实际的伤害
    34. float ActualDamage = BaseDamage;
    35. //得到命中物体表面材质
    36. EPhysicalSurface SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());
    37. //如果命中的是头部表面材质,伤害变成四倍
    38. if (SurfaceType == SURFACE_FLESHVULNERABLE)
    39. {
    40. ActualDamage *= 4;
    41. }
    42. //调用伤害函数
    43. //参数分别为伤害对象、基础伤害、设计方向、命中信息(命中句柄)、MyOwner->GetInstigatorController(暂时不了解)
    44. //this(伤害者) 和伤害类型
    45. UGameplayStatics::ApplyPointDamage(HitActor, ActualDamage, EyeRotator.Vector(), Hit, MyOwner->GetInstigatorController(), this, DamageType);
    46. //根据材质的不同,进行不同的处理
    47. UParticleSystem * SelectedEffect = nullptr;
    48. switch (SurfaceType)
    49. {
    50. //这两种情况是一个效果
    51. case SURFACE_FLESHDEFAULT:
    52. case SURFACE_FLESHVULNERABLE:
    53. SelectedEffect = FleshImpactEffect;
    54. break;
    55. default:
    56. SelectedEffect = DefaultImpactEffect;
    57. break;
    58. }
    59. //生成特效在命中点
    60. //ImpactEffect:特效 ImpactPoint:打击点 Rotation():打击方向
    61. if (SelectedEffect)
    62. {
    63. UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
    64. }
    65. //命中的时候,修改弹道特效的终点
    66. TraceEndPoint = Hit.ImpactPoint;
    67. }
    68. //方便debug
    69. DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::Red, false, 1, 0, 1);
    70. //射击特效
    71. PlayFireEffects(TraceEndPoint);
    72. }
    73. }

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

     测试

     

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

    武器类里面声明两个函数 

    1. //开始射击函数
    2. void StartFire();
    3. //停止设计函数
    4. void StoptFire();

    再声明几个变量

    1. //计时器句柄
    2. FTimerHandle TimerHandle_TimeBetweenShots;
    3. //上次开火时间点
    4. float FireLastTime;
    5. //开火的频率,每分钟多少枪
    6. UPROPERTY(EditDefaultsOnly, Category = "Weapon")
    7. float RateOfFire;
    8. //开火的间隔时间
    9. float TimeBetweenShots;

    在构造函数中初始化RateOfFire

    RateOfFire = 600;

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

    1. // Called when the game starts or when spawned
    2. void ASWeapen::BeginPlay()
    3. {
    4. Super::BeginPlay();
    5. TimeBetweenShots = 60 / RateOfFire;
    6. }

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

    1. void ASWeapen::Fire()
    2. {
    3. //创建一个撞击句柄,用来获取弹道相关信息
    4. FHitResult Hit;
    5. //弹道的起点,我们设置为角色眼睛的位置
    6. AActor * MyOwner = GetOwner();
    7. if (MyOwner)
    8. { //位置
    9. FVector EyeLocation;
    10. //方向
    11. FRotator EyeRotator;
    12. //得到眼睛的位置和角度
    13. MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotator);
    14. //弹道的终点就是起点+方向*10000
    15. FVector TraceEnd = EyeLocation + (EyeRotator.Vector() * 1000);
    16. //弹道特效的结束点
    17. FVector TraceEndPoint = TraceEnd;
    18. //设置碰撞通道为可见性通道
    19. FCollisionQueryParams QueryParams;
    20. //让射线忽略玩家和枪
    21. QueryParams.AddIgnoredActor(MyOwner);
    22. QueryParams.AddIgnoredActor(this);
    23. //符合追踪设为true,可以让射击更加精准
    24. QueryParams.bTraceComplex = true;
    25. //返回命中目标的表面材质
    26. QueryParams.bReturnPhysicalMaterial = true;
    27. //在创建一个单轨迹线来计算弹道
    28. //LineTraceSingleByChannel击中物体返回true
    29. if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, COLLISION_WEAPON, QueryParams))
    30. {
    31. //命中对象
    32. AActor * HitActor = Hit.GetActor();
    33. //实际的伤害
    34. float ActualDamage = BaseDamage;
    35. //得到命中物体表面材质
    36. EPhysicalSurface SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());
    37. //如果命中的是头部表面材质,伤害变成四倍
    38. if (SurfaceType == SURFACE_FLESHVULNERABLE)
    39. {
    40. ActualDamage *= 4;
    41. }
    42. //调用伤害函数
    43. //参数分别为伤害对象、基础伤害、设计方向、命中信息(命中句柄)、MyOwner->GetInstigatorController(暂时不了解)
    44. //this(伤害者) 和伤害类型
    45. UGameplayStatics::ApplyPointDamage(HitActor, ActualDamage, EyeRotator.Vector(), Hit, MyOwner->GetInstigatorController(), this, DamageType);
    46. //根据材质的不同,进行不同的处理
    47. UParticleSystem * SelectedEffect = nullptr;
    48. switch (SurfaceType)
    49. {
    50. //这两种情况是一个效果
    51. case SURFACE_FLESHDEFAULT:
    52. case SURFACE_FLESHVULNERABLE:
    53. SelectedEffect = FleshImpactEffect;
    54. break;
    55. default:
    56. SelectedEffect = DefaultImpactEffect;
    57. break;
    58. }
    59. //生成特效在命中点
    60. //ImpactEffect:特效 ImpactPoint:打击点 Rotation():打击方向
    61. if (SelectedEffect)
    62. {
    63. UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
    64. }
    65. //命中的时候,修改弹道特效的终点
    66. TraceEndPoint = Hit.ImpactPoint;
    67. }
    68. //方便debug
    69. DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::Red, false, 1, 0, 1);
    70. //射击特效
    71. PlayFireEffects(TraceEndPoint);
    72. //最后开火的时间
    73. FireLastTime = GetWorld()->TimeSeconds;
    74. }
    75. }

    实现这两个函数

    1. void ASWeapen::StartFire()
    2. {
    3. float FirstDelay = FMath::Max(0.0f, FireLastTime + TimeBetweenShots - GetWorld()->TimeSeconds);
    4. GetWorldTimerManager().SetTimer(TimerHandle_TimeBetweenShots, this, &ASWeapen::Fire, TimeBetweenShots, true, FirstDelay);
    5. }
    6. void ASWeapen::StoptFire()
    7. {
    8. GetWorldTimerManager().ClearTimer(TimerHandle_TimeBetweenShots);
    9. }

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

    1. //开始射击函数
    2. void StartFire();
    3. //停止设计函数
    4. void StoptFire();

    之前的fire函数就不要了

    然后定义函数

    1. void ASCharacter::StartFire()
    2. {
    3. if (CurrentWeapen1)
    4. {
    5. CurrentWeapen1->StartFire();
    6. }
    7. }
    8. void ASCharacter::StoptFire()
    9. {
    10. if (CurrentWeapen1)
    11. {
    12. CurrentWeapen1->StoptFire();
    13. }
    14. }

    绑定开火

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

  • 相关阅读:
    接收端编程、UDP编程练习、wireshrak抓包工具、UDP包头
    Synchronized 与 Lock 卖票问题、区别
    如何正确操作封箱机
    运行主程序后无法显示图形化界面的原因及其解决方法(拼图小游戏)
    修炼k8s+flink+hdfs+dlink(六:学习namespace,service)
    java-php-python-仁爱公益网站计算机毕业设计
    堆排序问题
    【笔记】逻辑斯蒂回归
    查找算法.
    Java 基础三:使用Velocity模板生成 xml
  • 原文地址:https://blog.csdn.net/zhang2362167998/article/details/127764064