六一的部落格


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




说明

  • 榴弹发生碰撞时对爆炸半径内Actor造成伤害
  • 可以在榴弹发射器中定义伤害相关参数, 如ShotDirection那样对榴弹进行设置; 选择直接在榴弹类中定义

概览

  • 重构武器
  • 注册碰撞委托, 在处理函数中对伤害半径内Actor造成伤害

重构武器


可配置参数的蓝图属性为EditDefaultsOnly

  1. ShootThemUp: Weapon/STUBaseWeapon.h

    VisiableAnywhere -> EditDefaultsOnly
    -
    DamageAmount
    TraceMaxDistance
    MuzzleSocketName
  2. ShootThemUp: Weapon/STURifleWeapon.h

    VisiableAnywhere -> EditDefaultsOnly
    -
    TimeBetweenShots
    BulletSpread

组件在原型和实例中均可见

VisibleDefaultsOnly -> VisibleAnywhere

ShootThemUp: Weapon/STUProjectile.h

-
CollisionComponent
MovementComponent

ASTUBaseWeapon::MakeDamage是STURifleWeapon的专属逻辑

将ASTUBaseWeapon::MakeDamage移动到Rifle

  1. 移动数据成员

    ShootThemUp: Weapon/STUBaseWeapon.h -> ShootThemUp: Weapon/STURifleWeapon.h
    1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
    2float DamageAmount = 10.0f;
  2. 移动函数声明

    ShootThemUp: Weapon/STUBaseWeapon.h -> ShootThemUp: Weapon/STURifleWeapon.h

    protected
    1void MakeDamage(const FHitResult& HitResult);                    
    
  3. 移动函数定义

    ShootThemUp: Weapon/STUBaseWeapon.cpp
    1void ASTUBaseWeapon::MakeDamage(const FHitResult &HitResult)
    2{
    3    const auto DamagedActor = HitResult.GetActor();
    4    if (!DamagedActor) return;
    5    DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), GetPlayerController(), this);
    6}
    ShootThemUp: Weapon/STURifleWeapon.cpp
    1#include "GameFramework/PlayerController.h" // TakeDamage的参数是AController
    2
    3void ASTURifleWeapon::MakeDamage(const FHitResult &HitResult)
    4{
    5    const auto DamagedActor = HitResult.GetActor();
    6    if (!DamagedActor) return;
    7    DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), GetPlayerController(), this);
    8}

将榴弹延时销毁逻辑从榴弹发射器类移动到榴弹类, 并添加参数

  1. 添加数据成员

    protected

    ShootThemUp: Weapon/STUProjectile.h
    1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
    2float LifeSeconds = 5.0f;
  2. 在BeginPlay中销毁榴弹

    ShootThemUp: Weapon/STUProjectile.cpp
    1SetLifeSpan(LifeSeconds);           
    
  3. 屏蔽榴弹发射器中的销毁逻辑

    ShootThemUp: Weapon/STULauncherWeapon.cpp

榴弹发生碰撞时, 对半径内Actor造成伤害

  1. 注册碰撞委托, 调用处理函数
  2. 处理函数中, 绘制爆炸半径, 并对半径内Actor造成伤害, 参照STUDevDamageActor

    ShootThemUp: Dev/STUDevDamageActor.cpp

注册碰撞委托


给出处理函数声明, 根据委托定义

  1. 委托定义

    UE_5.1/Engine/Source/Runtime/Engine/Classes/Components/PrimitiveComponent.h 184
    1DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams( FComponentHitSignature, UPrimitiveComponent, OnComponentHit, UPrimitiveComponent*, HitComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, FVector, NormalImpulse, const FHitResult&, Hit );
  2. 处理函数声明

    private

    ShootThemUp: Weapon/STUProjectile.h
    1UFUNCTION()
    2void OnProjectileHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
  3. 给出空定义

    ShootThemUp: Weapon/STUProjectile.cpp
    1void ASTUProjectile::OnProjectileHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {}

注册委托

  1. 委托成员

    UE_5.1/Engine/Source/Runtime/Engine/Classes/Components/PrimitiveComponent.h 1189
     1/** 
     2 *	Event called when a component hits (or is hit by) something solid. This could happen due to things like Character movement, using Set Location with 'sweep' enabled, or physics simulation.
     3 *	For events when objects overlap (e.g. walking into a trigger) see the 'Overlap' event.
     4 *
     5 *	@note For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled for this component.
     6 *	@note When receiving a hit from another object's movement, the directions of 'Hit.Normal' and 'Hit.ImpactNormal'
     7 *	will be adjusted to indicate force from the other object against this object.
     8 *	@note NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions.
     9 */
    10UPROPERTY(BlueprintAssignable, Category="Collision")
    11FComponentHitSignature OnComponentHit;
  2. 注册委托

    ShootThemUp: Weapon/STUProjectile.cpp
    1// BeginPlay
    2
    3check(CollisionComponent);
    4
    5CollisionComponent->OnComponentHit.AddDynamic(this, &ASTUProjectile::OnProjectileHit);

为榴弹设置上级

  1. 动态生成榴弹对象时, 设置上级为游戏角色
  2. 不对发射榴弹的游戏角色造成伤害
  3. 不与发射榴弹的游戏角色发生碰撞

ShootThemUp: Weapon/STULauncherWeapon.cpp

1Projectile->SetOwner(GetOwner());

设置碰撞组件

ShootThemUp: Weapon/STUProjectile.cpp

  1. 仅在计算轨迹时发生碰撞
    1// Constructor
    2CollisionComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
  2. 和所有通道发生碰撞
    1// Constructor
    2CollisionComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);                 
    
  3. 不与发射榴弹的游戏角色发生碰撞
    1// BeginPlay
    2 CollisionComponent->IgnoreActorWhenMoving(GetOwner(), true);

实现处理函数: 对爆炸半径内Actor造成伤害


伤害参数

-
伤害半径 DamageRadius
伤害数值 DamageAmount
伤害计算模型 DoFullDamage
伤害来源
忽略Actor列表

添加数据成员, 存放伤害参数

protected

ShootThemUp: Weapon/STUProjectile.h

1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
2float DamageRadius = 200.0f;
3
4UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
5float DamageAmount = 50.0f;
6
7UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
8bool DoFullDamage = false;

实现函数, 返回游戏角色控制器

  1. ShootThemUp: Weapon/STUProjectile.h

    private
    1AController* GetController() const;
  2. ShootThemUp: Weapon/STUProjectile.cpp
    1AController* ASTUProjectile::GetController() const
    2{
    3    const auto Pawn = Cast<APawn>(GetOwner());
    4    return Pawn ? Pawn->GetController() : nullptr;
    5}

实现处理函数

ShootThemUp: Weapon/STUProjectile.cpp

  1. 发生碰撞时, 榴弹不再运动

    通过将运动速度设为0实现; 联想到游戏角色死亡后调用DisableMovement
    1MovementComponent->StopMovementImmediately();
  2. 绘制爆炸范围
     1#include "DrawDebugHelpers.h"
     2
     3if (!GetWorld()) return;
     4DrawDebugSphere(GetWorld(),
     5                GetActorLocation(),
     6                DamageRadius,
     7                24,
     8                FColor::Red,
     9                false,
    10                5.0f);
  3. 对爆炸半径内Actor造成伤害

    排除榴弹上级
    1#include "Kismet/GameplayStatics.h"
    2#include "GameFramework/DamageType.h"
    3
    4UGameplayStatics::ApplyRadialDamage(GetWorld(), DamageAmount, GetActorLocation(), DamageRadius, UDamageType::StaticClass(), { GetOwner() }, this, GetController(), DoFullDamage);            
    
  4. 销毁榴弹对象
    1Destroy();

查看

  1. 无法伤害自己: 打地上


  2. 根据到球心的距离造成伤害


  3. 对处在爆炸半径内的游戏角色, 同时造成伤害


榴弹类造成伤害



说明

  • 榴弹发生碰撞时对爆炸半径内Actor造成伤害
  • 可以在榴弹发射器中定义伤害相关参数, 如ShotDirection那样对榴弹进行设置; 选择直接在榴弹类中定义

概览

  • 重构武器
  • 注册碰撞委托, 在处理函数中对伤害半径内Actor造成伤害

重构武器


可配置参数的蓝图属性为EditDefaultsOnly

  1. ShootThemUp: Weapon/STUBaseWeapon.h

    VisiableAnywhere -> EditDefaultsOnly
    -
    DamageAmount
    TraceMaxDistance
    MuzzleSocketName
  2. ShootThemUp: Weapon/STURifleWeapon.h

    VisiableAnywhere -> EditDefaultsOnly
    -
    TimeBetweenShots
    BulletSpread

组件在原型和实例中均可见

VisibleDefaultsOnly -> VisibleAnywhere

ShootThemUp: Weapon/STUProjectile.h

-
CollisionComponent
MovementComponent

ASTUBaseWeapon::MakeDamage是STURifleWeapon的专属逻辑

将ASTUBaseWeapon::MakeDamage移动到Rifle

  1. 移动数据成员

    ShootThemUp: Weapon/STUBaseWeapon.h -> ShootThemUp: Weapon/STURifleWeapon.h
    1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
    2float DamageAmount = 10.0f;
  2. 移动函数声明

    ShootThemUp: Weapon/STUBaseWeapon.h -> ShootThemUp: Weapon/STURifleWeapon.h

    protected
    1void MakeDamage(const FHitResult& HitResult);                    
    
  3. 移动函数定义

    ShootThemUp: Weapon/STUBaseWeapon.cpp
    1void ASTUBaseWeapon::MakeDamage(const FHitResult &HitResult)
    2{
    3    const auto DamagedActor = HitResult.GetActor();
    4    if (!DamagedActor) return;
    5    DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), GetPlayerController(), this);
    6}
    ShootThemUp: Weapon/STURifleWeapon.cpp
    1#include "GameFramework/PlayerController.h" // TakeDamage的参数是AController
    2
    3void ASTURifleWeapon::MakeDamage(const FHitResult &HitResult)
    4{
    5    const auto DamagedActor = HitResult.GetActor();
    6    if (!DamagedActor) return;
    7    DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), GetPlayerController(), this);
    8}

将榴弹延时销毁逻辑从榴弹发射器类移动到榴弹类, 并添加参数

  1. 添加数据成员

    protected

    ShootThemUp: Weapon/STUProjectile.h
    1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
    2float LifeSeconds = 5.0f;
  2. 在BeginPlay中销毁榴弹

    ShootThemUp: Weapon/STUProjectile.cpp
    1SetLifeSpan(LifeSeconds);           
    
  3. 屏蔽榴弹发射器中的销毁逻辑

    ShootThemUp: Weapon/STULauncherWeapon.cpp

榴弹发生碰撞时, 对半径内Actor造成伤害

  1. 注册碰撞委托, 调用处理函数
  2. 处理函数中, 绘制爆炸半径, 并对半径内Actor造成伤害, 参照STUDevDamageActor

    ShootThemUp: Dev/STUDevDamageActor.cpp

注册碰撞委托


给出处理函数声明, 根据委托定义

  1. 委托定义

    UE_5.1/Engine/Source/Runtime/Engine/Classes/Components/PrimitiveComponent.h 184
    1DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams( FComponentHitSignature, UPrimitiveComponent, OnComponentHit, UPrimitiveComponent*, HitComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, FVector, NormalImpulse, const FHitResult&, Hit );
  2. 处理函数声明

    private

    ShootThemUp: Weapon/STUProjectile.h
    1UFUNCTION()
    2void OnProjectileHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
  3. 给出空定义

    ShootThemUp: Weapon/STUProjectile.cpp
    1void ASTUProjectile::OnProjectileHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {}

注册委托

  1. 委托成员

    UE_5.1/Engine/Source/Runtime/Engine/Classes/Components/PrimitiveComponent.h 1189
     1/** 
     2 *	Event called when a component hits (or is hit by) something solid. This could happen due to things like Character movement, using Set Location with 'sweep' enabled, or physics simulation.
     3 *	For events when objects overlap (e.g. walking into a trigger) see the 'Overlap' event.
     4 *
     5 *	@note For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled for this component.
     6 *	@note When receiving a hit from another object's movement, the directions of 'Hit.Normal' and 'Hit.ImpactNormal'
     7 *	will be adjusted to indicate force from the other object against this object.
     8 *	@note NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions.
     9 */
    10UPROPERTY(BlueprintAssignable, Category="Collision")
    11FComponentHitSignature OnComponentHit;
  2. 注册委托

    ShootThemUp: Weapon/STUProjectile.cpp
    1// BeginPlay
    2
    3check(CollisionComponent);
    4
    5CollisionComponent->OnComponentHit.AddDynamic(this, &ASTUProjectile::OnProjectileHit);

为榴弹设置上级

  1. 动态生成榴弹对象时, 设置上级为游戏角色
  2. 不对发射榴弹的游戏角色造成伤害
  3. 不与发射榴弹的游戏角色发生碰撞

ShootThemUp: Weapon/STULauncherWeapon.cpp

1Projectile->SetOwner(GetOwner());

设置碰撞组件

ShootThemUp: Weapon/STUProjectile.cpp

  1. 仅在计算轨迹时发生碰撞
    1// Constructor
    2CollisionComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
  2. 和所有通道发生碰撞
    1// Constructor
    2CollisionComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);                 
    
  3. 不与发射榴弹的游戏角色发生碰撞
    1// BeginPlay
    2 CollisionComponent->IgnoreActorWhenMoving(GetOwner(), true);

实现处理函数: 对爆炸半径内Actor造成伤害


伤害参数

-
伤害半径 DamageRadius
伤害数值 DamageAmount
伤害计算模型 DoFullDamage
伤害来源
忽略Actor列表

添加数据成员, 存放伤害参数

protected

ShootThemUp: Weapon/STUProjectile.h

1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
2float DamageRadius = 200.0f;
3
4UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
5float DamageAmount = 50.0f;
6
7UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
8bool DoFullDamage = false;

实现函数, 返回游戏角色控制器

  1. ShootThemUp: Weapon/STUProjectile.h

    private
    1AController* GetController() const;
  2. ShootThemUp: Weapon/STUProjectile.cpp
    1AController* ASTUProjectile::GetController() const
    2{
    3    const auto Pawn = Cast<APawn>(GetOwner());
    4    return Pawn ? Pawn->GetController() : nullptr;
    5}

实现处理函数

ShootThemUp: Weapon/STUProjectile.cpp

  1. 发生碰撞时, 榴弹不再运动

    通过将运动速度设为0实现; 联想到游戏角色死亡后调用DisableMovement
    1MovementComponent->StopMovementImmediately();
  2. 绘制爆炸范围
     1#include "DrawDebugHelpers.h"
     2
     3if (!GetWorld()) return;
     4DrawDebugSphere(GetWorld(),
     5                GetActorLocation(),
     6                DamageRadius,
     7                24,
     8                FColor::Red,
     9                false,
    10                5.0f);
  3. 对爆炸半径内Actor造成伤害

    排除榴弹上级
    1#include "Kismet/GameplayStatics.h"
    2#include "GameFramework/DamageType.h"
    3
    4UGameplayStatics::ApplyRadialDamage(GetWorld(), DamageAmount, GetActorLocation(), DamageRadius, UDamageType::StaticClass(), { GetOwner() }, this, GetController(), DoFullDamage);            
    
  4. 销毁榴弹对象
    1Destroy();

查看

  1. 无法伤害自己: 打地上


  2. 根据到球心的距离造成伤害


  3. 对处在爆炸半径内的游戏角色, 同时造成伤害