六一的部落格


关关难过关关过,前路漫漫亦灿灿。




说明

  • 当前的STUBaseWeapon类基本实现了Rifle的逻辑, Launcher无连续射击和瞄准偏离逻辑
  • 创建STUBaseWeapon的派生类STURifleWeapon和STULauncherWeapon, 把Rifle的逻辑移动到STURifleWeapon, 使STUBaseWeapon成为一个武器意义上的抽象类
武器类
基类 STUBaseWeapon
派生类 Rifle STURifleWeapon
Launcher STULauncherWeapon

概览

  • 创建派生自STUBaseWeapon的C++类: STURifleWeapon和STULauncherWeapon
  • 调整STUBaseWeapon逻辑
  • 将Rifle的逻辑拷贝到STURifleWeapon
  • 创建基于STURifleWeapon和STULauncherWeapon的蓝图类, 并为之绑定武器模型
  • 验证Rifle逻辑正常

创建派生自STUBaseWeapon的C++类

类别 上级文件夹
STURifleWeapon Public Weapon
STULauncherWeapon Public Weapon

在内容浏览器选中C++ Classes > ShootThemUp > Public > Weapon > STUBaseWeapon, 右键




调整STUBaseWeapon逻辑


屏蔽连续射击

  1. 屏蔽射击定时器和时间间隔
  2. 将MakeShot声明为虚函数, 定义为空
  3. 将FireStart和FireStop定义为空

屏蔽瞄准偏离

  1. 将GetTraceData定义为虚函数, 屏蔽瞄准偏离逻辑
  2. 屏蔽圆锥偏移角参数

屏蔽头文件

1// #include "DrawDebugHelpers.h"
2// #include "TimerManager.h"

将STUBaseWeapon屏蔽的Rifle逻辑拷贝到STURifleWeapon


连续射击

  1. 定义射击定时器和时间间隔

    ShootThemUp: Weapon/STURifleWeapon.h
    • protected
      1UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
      2float TimeBetweenShots = 0.1f;
    • private
      1FTimerHandle ShotTimerHandle;
  2. 覆写虚函数MakeShot
    • ShootThemUp: Weapon/STURifleWeapon.h

      protected
      1virtual void MakeShot() override;
    • ShootThemUp: Weapon/STURifleWeapon.cpp
       1#include "Engine/World.h"
       2#include "DrawDebugHelpers.h"
       3
       4void ASTURifleWeapon::MakeShot()
       5{
       6    if (!GetWorld()) return;
       7
       8    FVector TraceStart, TraceEnd;
       9    if (!GetTraceData(TraceStart, TraceEnd)) return;         
      10
      11    FHitResult HitResult;
      12    MakeHit(HitResult, TraceStart, TraceEnd);
      13
      14    if (HitResult.bBlockingHit)
      15    {
      16        DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), HitResult.ImpactPoint, FColor::Red, false, 3.0f, 0, 3.0f);
      17        DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.0f, 24, FColor::Red, false, 5.0f);
      18        MakeDamage(HitResult);
      19    }
      20    else
      21    {
      22        DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), TraceEnd, FColor::Red, false, 3.0f, 0, 3.0f);
      23    }
      24}
  3. 覆写FireStart和FireStop
    • ShootThemUp: Weapon/STURifleWeapon.h

      public
      1virtual void FireStart() override;
      2virtual void FireStop() override;
    • ShootThemUp: Weapon/STURifleWeapon.cpp
       1#include "TimerManager.h"
       2
       3void ASTURifleWeapon::FireStart()
       4{
       5    MakeShot();
       6    GetWorldTimerManager().SetTimer(ShotTimerHandle, this, &ASTURifleWeapon::MakeShot, TimeBetweenShots, true);
       7}
       8
       9void ASTURifleWeapon::FireStop()
      10{
      11    GetWorldTimerManager().ClearTimer(ShotTimerHandle);
      12}

瞄准偏离

  1. 定义偏移角

    protected

    ShootThemUp: Weapon/STURifleWeapon.cpp
    1UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
    2float BulletSpread = 1.5f;
  2. 覆写GetTraceData
    • ShootThemUp: Weapon/STURifleWeapon.h

      protected
      1virtual void GetTraceData(FVector& TraceStart, FVector& TraceEnd) const override;
    • ShootThemUp: Weapon/STURifleWeapon.cpp
       1bool ASTURifleWeapon::GetTraceData(FVector& TraceStart, FVector& TraceEnd) const
       2{
       3    FVector ViewLocation;
       4     FRotator ViewRotation;
       5    if (!GetPlayerViewPoint(ViewLocation, ViewRotation)) return false;
       6
       7    TraceStart = ViewLocation;
       8
       9    const auto HalfRad = FMath::DegreesToRadians(BulletSpread);
      10    const FVector ShootDirection = FMath::VRandCone(ViewRotation.Vector(), HalfRad);
      11
      12    TraceEnd = TraceStart + ShootDirection * TraceMaxDistance;
      13    return true;
      14}

创建基于STURifleWeapon和STULauncherWeapon的蓝图类

保存到Content/Weapon/目录下



测试BP_STURifleWeapon

  1. 为BP_STURifleWeapon绑定武器模型Rifle
  2. 设置游戏角色武器类属性为BP_STURifleWeapon
  3. 功能正常

测试BP_STULauncherWeapon

  1. 为BP_STULauncherWeapon绑定武器模型Launcher

  2. 设置游戏角色武器类属性为BP_STULauncherWeapon

  3. 武器正常显示, 射击无反应


武器派生类



说明

  • 当前的STUBaseWeapon类基本实现了Rifle的逻辑, Launcher无连续射击和瞄准偏离逻辑
  • 创建STUBaseWeapon的派生类STURifleWeapon和STULauncherWeapon, 把Rifle的逻辑移动到STURifleWeapon, 使STUBaseWeapon成为一个武器意义上的抽象类
武器类
基类 STUBaseWeapon
派生类 Rifle STURifleWeapon
Launcher STULauncherWeapon

概览

  • 创建派生自STUBaseWeapon的C++类: STURifleWeapon和STULauncherWeapon
  • 调整STUBaseWeapon逻辑
  • 将Rifle的逻辑拷贝到STURifleWeapon
  • 创建基于STURifleWeapon和STULauncherWeapon的蓝图类, 并为之绑定武器模型
  • 验证Rifle逻辑正常

创建派生自STUBaseWeapon的C++类

类别 上级文件夹
STURifleWeapon Public Weapon
STULauncherWeapon Public Weapon

在内容浏览器选中C++ Classes > ShootThemUp > Public > Weapon > STUBaseWeapon, 右键




调整STUBaseWeapon逻辑


屏蔽连续射击

  1. 屏蔽射击定时器和时间间隔
  2. 将MakeShot声明为虚函数, 定义为空
  3. 将FireStart和FireStop定义为空

屏蔽瞄准偏离

  1. 将GetTraceData定义为虚函数, 屏蔽瞄准偏离逻辑
  2. 屏蔽圆锥偏移角参数

屏蔽头文件

1// #include "DrawDebugHelpers.h"
2// #include "TimerManager.h"

将STUBaseWeapon屏蔽的Rifle逻辑拷贝到STURifleWeapon


连续射击

  1. 定义射击定时器和时间间隔

    ShootThemUp: Weapon/STURifleWeapon.h
    • protected
      1UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
      2float TimeBetweenShots = 0.1f;
    • private
      1FTimerHandle ShotTimerHandle;
  2. 覆写虚函数MakeShot
    • ShootThemUp: Weapon/STURifleWeapon.h

      protected
      1virtual void MakeShot() override;
    • ShootThemUp: Weapon/STURifleWeapon.cpp
       1#include "Engine/World.h"
       2#include "DrawDebugHelpers.h"
       3
       4void ASTURifleWeapon::MakeShot()
       5{
       6    if (!GetWorld()) return;
       7
       8    FVector TraceStart, TraceEnd;
       9    if (!GetTraceData(TraceStart, TraceEnd)) return;         
      10
      11    FHitResult HitResult;
      12    MakeHit(HitResult, TraceStart, TraceEnd);
      13
      14    if (HitResult.bBlockingHit)
      15    {
      16        DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), HitResult.ImpactPoint, FColor::Red, false, 3.0f, 0, 3.0f);
      17        DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.0f, 24, FColor::Red, false, 5.0f);
      18        MakeDamage(HitResult);
      19    }
      20    else
      21    {
      22        DrawDebugLine(GetWorld(), GetMuzzleWorldLocation(), TraceEnd, FColor::Red, false, 3.0f, 0, 3.0f);
      23    }
      24}
  3. 覆写FireStart和FireStop
    • ShootThemUp: Weapon/STURifleWeapon.h

      public
      1virtual void FireStart() override;
      2virtual void FireStop() override;
    • ShootThemUp: Weapon/STURifleWeapon.cpp
       1#include "TimerManager.h"
       2
       3void ASTURifleWeapon::FireStart()
       4{
       5    MakeShot();
       6    GetWorldTimerManager().SetTimer(ShotTimerHandle, this, &ASTURifleWeapon::MakeShot, TimeBetweenShots, true);
       7}
       8
       9void ASTURifleWeapon::FireStop()
      10{
      11    GetWorldTimerManager().ClearTimer(ShotTimerHandle);
      12}

瞄准偏离

  1. 定义偏移角

    protected

    ShootThemUp: Weapon/STURifleWeapon.cpp
    1UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
    2float BulletSpread = 1.5f;
  2. 覆写GetTraceData
    • ShootThemUp: Weapon/STURifleWeapon.h

      protected
      1virtual void GetTraceData(FVector& TraceStart, FVector& TraceEnd) const override;
    • ShootThemUp: Weapon/STURifleWeapon.cpp
       1bool ASTURifleWeapon::GetTraceData(FVector& TraceStart, FVector& TraceEnd) const
       2{
       3    FVector ViewLocation;
       4     FRotator ViewRotation;
       5    if (!GetPlayerViewPoint(ViewLocation, ViewRotation)) return false;
       6
       7    TraceStart = ViewLocation;
       8
       9    const auto HalfRad = FMath::DegreesToRadians(BulletSpread);
      10    const FVector ShootDirection = FMath::VRandCone(ViewRotation.Vector(), HalfRad);
      11
      12    TraceEnd = TraceStart + ShootDirection * TraceMaxDistance;
      13    return true;
      14}

创建基于STURifleWeapon和STULauncherWeapon的蓝图类

保存到Content/Weapon/目录下



测试BP_STURifleWeapon

  1. 为BP_STURifleWeapon绑定武器模型Rifle
  2. 设置游戏角色武器类属性为BP_STURifleWeapon
  3. 功能正常

测试BP_STULauncherWeapon

  1. 为BP_STULauncherWeapon绑定武器模型Launcher

  2. 设置游戏角色武器类属性为BP_STULauncherWeapon

  3. 武器正常显示, 射击无反应