六一的部落格


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




说明

  1. C++
  2. 治疗机制
    • 受到伤害则延缓治疗;不再受到伤害才会自动治疗
    • 使用定时器实现
  3. 获取定时器管理对象
    • UActorComponent::GetOwner > AActor::GetWorldTimerManager
    • UActorComponent::GetWorld > UWorld::GetTimerManager

实现自动治疗


添加治疗参数

protected

参数 名称
使能自动治疗 AutoHeal
首次治疗延后时长 HealDelay
恢复生命值周期 HealRate
单次恢复量 HealModifier

ShootThemUp: Components/STUHealthComponent.h

 1UPROPERTY(EditDefaultsOnly)
 2bool AutoHeal = true;
 3
 4UPROPERTY(EditDefaultsOnly, meta = (EditCondition = "AutoHeal"))
 5float HealRate = 1.0f;
 6
 7UPROPERTY(EditDefaultsOnly, meta = (EditCondition = "AutoHeal"))
 8float HealDelay = 3.0f;
 9
10UPROPERTY(EditDefaultsOnly, meta = (EditCondition = "AutoHeal"))
11float HealModifier = 5.0f;

添加定时器


添加数据成员

private

ShootThemUp: Components/STUHealthComponent.h

1FTimerHandle HealTimer;

搭建框架

  • 添加空的回调函数

    ShootThemUp: Components/STUHealthComponent.cpp

    1void USTUHealthComponent::OnHeal() {}
  • 定时器接口

    ShootThemUp: Components/STUHealthComponent.cpp

    1. 头文件
      1#include "Engine/World.h"
      2#include "TimerManager.h"
    2. 开启定时器
       1void USTUHealthComponent::StartHealTimer()
       2{
       3    if (AutoHeal && GetWorld())
       4    {
       5        GetWorld()->GetTimerManager().SetTimer(HealTimer, 
       6                                               this,
       7                                               &USTUHealthComponent::OnHeal,
       8                                               HealRate, 
       9                                               true, 
      10                                               HealDelay);
      11    }
      12}
    3. 关闭定时器
      1void USTUHealthComponent::StopHealTimer()
      2{
      3    if (AutoHeal && GetWorld())
      4    {
      5        GetWorld()->GetTimerManager().ClearTimer(HealTimer);
      6    }
      7}
    4. 接口声明

      private

      ShootThemUp: Components/STUHealthComponent.h
  • 回调函数声明

    private

    ShootThemUp: Components/STUHealthComponent.h


回调函数实现

ShootThemUp: Components/STUHealthComponent.cpp

1void USTUHealthComponent::OnHeal()
2{
3    SetHealth(Health + HealModifier);
4    if (FMath::IsNearlyEqual(Health, MaxHealth))
5    {
6        StopHealTimer();
7    }
8}

游戏角色受到伤害延缓治疗

ShootThemUp: Components/STUHealthComponent.cpp

 1void USTUHealthComponent::OnTakeAnyDamage(AActor *DamagedActor, float Damage, const UDamageType *DamageType, AController *InstigatedBy,
 2                                          AActor *DamageCauser)
 3{
 4    if (Damage <= 0.0f || IsDead())
 5        return;
 6
 7    if (!FMath::IsNearlyEqual(Health, MaxHealth))
 8        StopHealTimer();
 9
10    // Health -= Damage;
11    SetHealth(Health - Damage);
12    UE_LOG(LogHealthComponent, Display, TEXT("Damage: %.0f"), Damage);
13
14    if (DamageType)
15    {
16        if (DamageType->IsA<USTUFireDamageType>())
17        {
18            UE_LOG(LogHealthComponent, Display, TEXT("So Hooooooot !!!"));
19        }
20        else if (DamageType->IsA<USTUIceDamageType>())
21        {
22            UE_LOG(LogHealthComponent, Display, TEXT("So Cooooooooold !!!"));
23        }
24    }
25
26    if (IsDead())
27    {
28        OnDeath.Broadcast();
29    }
30    else
31    {
32        StartHealTimer();
33    }
34}

重写IsDead

ShootThemUp: Components/STUHealthComponent.h

1bool IsDead() const { return FMath::IsNearlyZero(Health); }

自动治疗



说明

  1. C++
  2. 治疗机制
    • 受到伤害则延缓治疗;不再受到伤害才会自动治疗
    • 使用定时器实现
  3. 获取定时器管理对象
    • UActorComponent::GetOwner > AActor::GetWorldTimerManager
    • UActorComponent::GetWorld > UWorld::GetTimerManager

实现自动治疗


添加治疗参数

protected

参数 名称
使能自动治疗 AutoHeal
首次治疗延后时长 HealDelay
恢复生命值周期 HealRate
单次恢复量 HealModifier

ShootThemUp: Components/STUHealthComponent.h

 1UPROPERTY(EditDefaultsOnly)
 2bool AutoHeal = true;
 3
 4UPROPERTY(EditDefaultsOnly, meta = (EditCondition = "AutoHeal"))
 5float HealRate = 1.0f;
 6
 7UPROPERTY(EditDefaultsOnly, meta = (EditCondition = "AutoHeal"))
 8float HealDelay = 3.0f;
 9
10UPROPERTY(EditDefaultsOnly, meta = (EditCondition = "AutoHeal"))
11float HealModifier = 5.0f;

添加定时器


添加数据成员

private

ShootThemUp: Components/STUHealthComponent.h

1FTimerHandle HealTimer;

搭建框架

  • 添加空的回调函数

    ShootThemUp: Components/STUHealthComponent.cpp

    1void USTUHealthComponent::OnHeal() {}
  • 定时器接口

    ShootThemUp: Components/STUHealthComponent.cpp

    1. 头文件
      1#include "Engine/World.h"
      2#include "TimerManager.h"
    2. 开启定时器
       1void USTUHealthComponent::StartHealTimer()
       2{
       3    if (AutoHeal && GetWorld())
       4    {
       5        GetWorld()->GetTimerManager().SetTimer(HealTimer, 
       6                                               this,
       7                                               &USTUHealthComponent::OnHeal,
       8                                               HealRate, 
       9                                               true, 
      10                                               HealDelay);
      11    }
      12}
    3. 关闭定时器
      1void USTUHealthComponent::StopHealTimer()
      2{
      3    if (AutoHeal && GetWorld())
      4    {
      5        GetWorld()->GetTimerManager().ClearTimer(HealTimer);
      6    }
      7}
    4. 接口声明

      private

      ShootThemUp: Components/STUHealthComponent.h
  • 回调函数声明

    private

    ShootThemUp: Components/STUHealthComponent.h


回调函数实现

ShootThemUp: Components/STUHealthComponent.cpp

1void USTUHealthComponent::OnHeal()
2{
3    SetHealth(Health + HealModifier);
4    if (FMath::IsNearlyEqual(Health, MaxHealth))
5    {
6        StopHealTimer();
7    }
8}

游戏角色受到伤害延缓治疗

ShootThemUp: Components/STUHealthComponent.cpp

 1void USTUHealthComponent::OnTakeAnyDamage(AActor *DamagedActor, float Damage, const UDamageType *DamageType, AController *InstigatedBy,
 2                                          AActor *DamageCauser)
 3{
 4    if (Damage <= 0.0f || IsDead())
 5        return;
 6
 7    if (!FMath::IsNearlyEqual(Health, MaxHealth))
 8        StopHealTimer();
 9
10    // Health -= Damage;
11    SetHealth(Health - Damage);
12    UE_LOG(LogHealthComponent, Display, TEXT("Damage: %.0f"), Damage);
13
14    if (DamageType)
15    {
16        if (DamageType->IsA<USTUFireDamageType>())
17        {
18            UE_LOG(LogHealthComponent, Display, TEXT("So Hooooooot !!!"));
19        }
20        else if (DamageType->IsA<USTUIceDamageType>())
21        {
22            UE_LOG(LogHealthComponent, Display, TEXT("So Cooooooooold !!!"));
23        }
24    }
25
26    if (IsDead())
27    {
28        OnDeath.Broadcast();
29    }
30    else
31    {
32        StartHealTimer();
33    }
34}

重写IsDead

ShootThemUp: Components/STUHealthComponent.h

1bool IsDead() const { return FMath::IsNearlyZero(Health); }