榴弹类造成伤害
2023年8月25日 2024年1月11日
说明
- 榴弹发生碰撞时对爆炸半径内Actor造成伤害
- 可以在榴弹发射器中定义伤害相关参数, 如ShotDirection那样对榴弹进行设置; 选择直接在榴弹类中定义
概览
- 重构武器
- 注册碰撞委托, 在处理函数中对伤害半径内Actor造成伤害
重构武器
可配置参数的蓝图属性为EditDefaultsOnly
ShootThemUp: Weapon/STUBaseWeapon.h
VisiableAnywhere -> EditDefaultsOnly
- DamageAmount TraceMaxDistance MuzzleSocketName ShootThemUp: Weapon/STURifleWeapon.h
VisiableAnywhere -> EditDefaultsOnly
- TimeBetweenShots BulletSpread
组件在原型和实例中均可见
VisibleDefaultsOnly -> VisibleAnywhere
ShootThemUp: Weapon/STUProjectile.h
- |
---|
CollisionComponent |
MovementComponent |
ASTUBaseWeapon::MakeDamage是STURifleWeapon的专属逻辑
将ASTUBaseWeapon::MakeDamage移动到Rifle
- 移动数据成员
ShootThemUp: Weapon/STUBaseWeapon.h
->ShootThemUp: Weapon/STURifleWeapon.h
1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) 2float DamageAmount = 10.0f;
- 移动函数声明
ShootThemUp: Weapon/STUBaseWeapon.h
->ShootThemUp: Weapon/STURifleWeapon.h
protected
1void MakeDamage(const FHitResult& HitResult);
- 移动函数定义
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}
将榴弹延时销毁逻辑从榴弹发射器类移动到榴弹类, 并添加参数
- 添加数据成员
protected
ShootThemUp: Weapon/STUProjectile.h
1UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) 2float LifeSeconds = 5.0f;
- 在BeginPlay中销毁榴弹
ShootThemUp: Weapon/STUProjectile.cpp
1SetLifeSpan(LifeSeconds);
- 屏蔽榴弹发射器中的销毁逻辑
ShootThemUp: Weapon/STULauncherWeapon.cpp
榴弹发生碰撞时, 对半径内Actor造成伤害
- 注册碰撞委托, 调用处理函数
- 处理函数中, 绘制爆炸半径, 并对半径内Actor造成伤害, 参照STUDevDamageActor
ShootThemUp: Dev/STUDevDamageActor.cpp
注册碰撞委托
给出处理函数声明, 根据委托定义
- 委托定义
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 );
- 处理函数声明
private
ShootThemUp: Weapon/STUProjectile.h
1UFUNCTION() 2void OnProjectileHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
- 给出空定义
ShootThemUp: Weapon/STUProjectile.cpp
1void ASTUProjectile::OnProjectileHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {}
注册委托
- 委托成员
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;
- 注册委托
ShootThemUp: Weapon/STUProjectile.cpp
1// BeginPlay 2 3check(CollisionComponent); 4 5CollisionComponent->OnComponentHit.AddDynamic(this, &ASTUProjectile::OnProjectileHit);
为榴弹设置上级
- 动态生成榴弹对象时, 设置上级为游戏角色
- 不对发射榴弹的游戏角色造成伤害
- 不与发射榴弹的游戏角色发生碰撞
ShootThemUp: Weapon/STULauncherWeapon.cpp
1Projectile->SetOwner(GetOwner());
设置碰撞组件
ShootThemUp: Weapon/STUProjectile.cpp
- 仅在计算轨迹时发生碰撞
1// Constructor 2CollisionComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
- 和所有通道发生碰撞
1// Constructor 2CollisionComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
- 不与发射榴弹的游戏角色发生碰撞
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;
实现函数, 返回游戏角色控制器
ShootThemUp: Weapon/STUProjectile.h
private
1AController* GetController() const;
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
- 发生碰撞时, 榴弹不再运动
通过将运动速度设为0实现; 联想到游戏角色死亡后调用DisableMovement
1MovementComponent->StopMovementImmediately();
- 绘制爆炸范围
1#include "DrawDebugHelpers.h" 2 3if (!GetWorld()) return; 4DrawDebugSphere(GetWorld(), 5 GetActorLocation(), 6 DamageRadius, 7 24, 8 FColor::Red, 9 false, 10 5.0f);
- 对爆炸半径内Actor造成伤害
排除榴弹上级
1#include "Kismet/GameplayStatics.h" 2#include "GameFramework/DamageType.h" 3 4UGameplayStatics::ApplyRadialDamage(GetWorld(), DamageAmount, GetActorLocation(), DamageRadius, UDamageType::StaticClass(), { GetOwner() }, this, GetController(), DoFullDamage);
- 销毁榴弹对象
1Destroy();
查看
-
无法伤害自己: 打地上
-
根据到球心的距离造成伤害
-
对处在爆炸半径内的游戏角色, 同时造成伤害