六一的部落格


行百里者半九十




说明

  1. 生命值修改时, 同步到HealthTextComponent组件
  2. 生命值为0, 销毁游戏角色
  3. 死亡时, 播放死亡动画

动画剪辑

Animation Montage

  • 可以将多个动画组合播放. 把希望连续播放的动画添加到时间线 timeline , 在代码或蓝图中播放动画剪辑
  • 命名:以AM_打头

Slot

若此时播放动画剪辑, 输出输入动画和动画剪辑的拼接;若无动画剪辑在播放, 输出输入动画


添加委托:当生命值更改时, 同步到HealthTextComponent文本

C++


屏蔽当前HealthTextComponent文本的设置

ShootThemUp: Player/STUBaseCharacter.cpp

屏蔽Tick函数中的文本更新


初始化HealthTextComponent文本

ShootThemUp: Player/STUBaseCharacter.cpp

1// BeginPlay
2HealthTextComponent->SetText(FText::FromString(FString::Printf(TEXT("%.0f"), HealthComponent->GetHealth())));

HealthComponent提供委托服务: 生命值修改通知

-
多播
仅C++

在HealthComponent定义委托类型FChangeHealthSignature

ShootThemUp: Components/STUHealthComponent.h

1DECLARE_MULTICAST_DELEGATE(FChangeHealthSignature);

添加数据成员OnChangeHealth, 提供委托服务

public

ShootThemUp: Components/STUHealthComponent.h

1FChangeHealthSignature OnChangeHealth;

封装修改Health逻辑, 调用时通知客户端

只能通过SetHealth接口修改生命值

  1. 函数定义

    ShootThemUp: Components/STUHealthComponent.cpp
    1void USTUHealthComponent::SetHealth(float NewHealth)
    2{
    3    Health = NewHealth;
    4    OnChangeHealth.Broadcast();
    5}
  2. 函数声明

    private

    ShootThemUp: Components/STUHealthComponent.h

修改OnTakeAnyDamage

ShootThemUp: Components/STUHealthComponent.cpp

1// Health -= Damage;
2SetHealth(Health - Damage);

STUBaseCharacter注册委托服务: OnChangeHealth

-
仅C++ AddUObject

搭建框架: 注册生命值修改通知

  1. 添加空函数

    ShootThemUp: Player/STUBaseCharacter.cpp
    1void ASTUBaseCharacter::OnChangeHealth() {}
  2. 注册委托服务

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// BeginPlay
    2HealthComponent->OnChangeHealth.AddUObject(this, &ASTUBaseCharacter::OnChangeHealth);
  3. 函数声明

    private

    ShootThemUp: Player/STUBaseCharacter.h

实现处理函数OnChangeHealth

设置HealthTextComponent文本

ShootThemUp: Player/STUBaseCharacter.cpp

1// OnChangeHealth
2HealthTextComponent->SetText(FText::FromString(FString::Printf(TEXT("%.0f"), HealthComponent->GetHealth())));

Character和其组件调用BeginPlay的先后顺序

先调用Component的BeginPlay, 再调用Character的BeginPlay.

先由HealthComponent在BeginPlay初始化Health, 才轮到Character在BeginPlay中注册服务.

若我们没有在Character的BeginPlay中初始化HealthTextComponent文本, 当Character在BeginPlay中注册服务完成, HealthTextComponent 文本显示为0. 直到Health再次被更改, Character才会收到通知同步.


游戏角色死亡后, 生命值不再减少

C++


提供接口, 判断Character是否死亡

public

ShootThemUp: Components/STUHealthComponent.h

1UFUNCTION(BlueprintCallable)
2bool IsDead() const { return Health <= 0.0f; }

Character死亡之后, 生命值不再减少

若伤害的数量特征不大于0, 或者当前生命值不大于0, 无法继续对Character造成伤害

ShootThemUp: Components/STUHealthComponent.cpp

1// OnTakeAnyDamage
2if (Damage <= 0.0f || IsDead()) return;

限制Health范围

ShootThemUp: Components/STUHealthComponent.cpp

1// Health = NewHealth;
2Health = FMath::Clamp(NewHealth, 0.0f, MaxHealth);

添加委托:游戏角色死亡, 销毁Character

C++

当生命值发生改变时修改HealthText文本, 当生命值变为0时销毁Character, 一码归一码


HealthComponent提供委托服务: 游戏角色死亡通知

-
多播
仅C++

在HealthComponent定义委托类型FDeathSignature

ShootThemUp: Components/STUHealthComponent.h

1DECLARE_MULTICAST_DELEGATE(FDeathSignature);

添加数据成员OnDeath, 提供委托服务

public

ShootThemUp: Components/STUHealthComponent.h

1FDeathSignature OnDeath;         

Character死亡, 通知客户端

ShootThemUp: Components/STUHealthComponent.cpp

1// OnTakeAnyDamage
2if (IsDead())
3{
4    OnDeath.Broadcast();
5}

STUBaseCharacter注册委托服务: OnDeath

-
仅C++ AddUObject

搭建框架: 注册死亡通知

  1. 添加空函数

    ShootThemUp: Player/STUBaseCharacter.cpp
    1void ASTUBaseCharacter::OnDeath() {}     
    
  2. 注册委托服务

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// BeginPlay
    2HealthComponent->OnDeath.AddUObject(this, &ASTUBaseCharacter::OnDeath);            
    
  3. 函数声明

    private

    ShootThemUp: Player/STUBaseCharacter.h

实现处理函数OnDeath

  1. 添加销毁延时

    protected

    ShootThemUp: Player/STUBaseCharacter.h
    1UPROPERTY(EditDefaultsOnly, meta = (ClampMin = "0.0", ClampMax = "10.0"))
    2float LifeSpanOnDeath = 5.0f;
  2. 检查CharacterMovement组件有效性

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// BeginPlay
    2check(GetCharacterMovement());
  3. 剥夺玩家对游戏角色的控制权, 开启定时器销毁Character

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// OnDeath
    2GetCharacterMovement()->DisableMovement();
    3SetLifeSpan(LifeSpanOnDeath);

创建死亡动画剪辑

虚幻编辑器

之前的跳跃、跑步、转向动画, 均对应状态机中的一个状态. 如果游戏角色死亡拥有对应状态, 每个状态都可能迁移到死亡状态, 光是想想都觉得麻烦

使用动画剪辑 AnimMontage 资产, 当游戏角色死亡时, 播放死亡动画剪辑, 通过slot连接当前动画和死亡动画剪辑


创建AnimMontage资产

-
死亡动画资产 ExternalContent/Animation/Animations/TTP_Animations/Death
  1. 选中死亡动画资产, 右键 > Create > Create AnimMontage > 命名为AM_Death


  2. 移动到Content/Player/Animations路径下



在动画蓝图中添加Slot

ABP_BaseCharacter > AnimGraph


在Locomotion和OutputPose之间添加Slot



Slot和AM_Death的分组一致

  1. Slot

    -
    SlotName DefaultGroup.DefaultSlot


  2. AM_Death

    -
    Montage DefaultGroup.DefaultSlot



设置动画剪辑

AM_Death

死亡动画结束后, 不再播放其他动画

Asset Details > BlendOptions > EnableAutoBlendOut, 取消勾选



游戏角色死亡时, 播放动画剪辑

C++

C++类型
动画剪辑 AnimMontage UAnimMontage

添加UAnimMontage类型数据成员

protected

ShootThemUp: Player/STUBaseCharacter.h

1UPROPERTY(EditDefaultsOnly)
2UAnimMontage *DeathAnimMontage;

Character死亡时, 播放动画剪辑

ShootThemUp: Player/STUBaseCharacter.cpp

1// OnDeath
2PlayAnimMontage(DeathAnimMontage);

查看

虚幻编辑器

  1. 设置游戏角色死亡时播放的动画剪辑

    BP_STUBaseCharacter


  2. 效果图


    禁止移动Character之后, 销毁Character之前, 仍可以移动Camera;即, 水平旋转视角时可以旋转Character


添加游戏角色死亡逻辑



说明

  1. 生命值修改时, 同步到HealthTextComponent组件
  2. 生命值为0, 销毁游戏角色
  3. 死亡时, 播放死亡动画

动画剪辑

Animation Montage

  • 可以将多个动画组合播放. 把希望连续播放的动画添加到时间线 timeline , 在代码或蓝图中播放动画剪辑
  • 命名:以AM_打头

Slot

若此时播放动画剪辑, 输出输入动画和动画剪辑的拼接;若无动画剪辑在播放, 输出输入动画


添加委托:当生命值更改时, 同步到HealthTextComponent文本

C++


屏蔽当前HealthTextComponent文本的设置

ShootThemUp: Player/STUBaseCharacter.cpp

屏蔽Tick函数中的文本更新


初始化HealthTextComponent文本

ShootThemUp: Player/STUBaseCharacter.cpp

1// BeginPlay
2HealthTextComponent->SetText(FText::FromString(FString::Printf(TEXT("%.0f"), HealthComponent->GetHealth())));

HealthComponent提供委托服务: 生命值修改通知

-
多播
仅C++

在HealthComponent定义委托类型FChangeHealthSignature

ShootThemUp: Components/STUHealthComponent.h

1DECLARE_MULTICAST_DELEGATE(FChangeHealthSignature);

添加数据成员OnChangeHealth, 提供委托服务

public

ShootThemUp: Components/STUHealthComponent.h

1FChangeHealthSignature OnChangeHealth;

封装修改Health逻辑, 调用时通知客户端

只能通过SetHealth接口修改生命值

  1. 函数定义

    ShootThemUp: Components/STUHealthComponent.cpp
    1void USTUHealthComponent::SetHealth(float NewHealth)
    2{
    3    Health = NewHealth;
    4    OnChangeHealth.Broadcast();
    5}
  2. 函数声明

    private

    ShootThemUp: Components/STUHealthComponent.h

修改OnTakeAnyDamage

ShootThemUp: Components/STUHealthComponent.cpp

1// Health -= Damage;
2SetHealth(Health - Damage);

STUBaseCharacter注册委托服务: OnChangeHealth

-
仅C++ AddUObject

搭建框架: 注册生命值修改通知

  1. 添加空函数

    ShootThemUp: Player/STUBaseCharacter.cpp
    1void ASTUBaseCharacter::OnChangeHealth() {}
  2. 注册委托服务

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// BeginPlay
    2HealthComponent->OnChangeHealth.AddUObject(this, &ASTUBaseCharacter::OnChangeHealth);
  3. 函数声明

    private

    ShootThemUp: Player/STUBaseCharacter.h

实现处理函数OnChangeHealth

设置HealthTextComponent文本

ShootThemUp: Player/STUBaseCharacter.cpp

1// OnChangeHealth
2HealthTextComponent->SetText(FText::FromString(FString::Printf(TEXT("%.0f"), HealthComponent->GetHealth())));

Character和其组件调用BeginPlay的先后顺序

先调用Component的BeginPlay, 再调用Character的BeginPlay.

先由HealthComponent在BeginPlay初始化Health, 才轮到Character在BeginPlay中注册服务.

若我们没有在Character的BeginPlay中初始化HealthTextComponent文本, 当Character在BeginPlay中注册服务完成, HealthTextComponent 文本显示为0. 直到Health再次被更改, Character才会收到通知同步.


游戏角色死亡后, 生命值不再减少

C++


提供接口, 判断Character是否死亡

public

ShootThemUp: Components/STUHealthComponent.h

1UFUNCTION(BlueprintCallable)
2bool IsDead() const { return Health <= 0.0f; }

Character死亡之后, 生命值不再减少

若伤害的数量特征不大于0, 或者当前生命值不大于0, 无法继续对Character造成伤害

ShootThemUp: Components/STUHealthComponent.cpp

1// OnTakeAnyDamage
2if (Damage <= 0.0f || IsDead()) return;

限制Health范围

ShootThemUp: Components/STUHealthComponent.cpp

1// Health = NewHealth;
2Health = FMath::Clamp(NewHealth, 0.0f, MaxHealth);

添加委托:游戏角色死亡, 销毁Character

C++

当生命值发生改变时修改HealthText文本, 当生命值变为0时销毁Character, 一码归一码


HealthComponent提供委托服务: 游戏角色死亡通知

-
多播
仅C++

在HealthComponent定义委托类型FDeathSignature

ShootThemUp: Components/STUHealthComponent.h

1DECLARE_MULTICAST_DELEGATE(FDeathSignature);

添加数据成员OnDeath, 提供委托服务

public

ShootThemUp: Components/STUHealthComponent.h

1FDeathSignature OnDeath;         

Character死亡, 通知客户端

ShootThemUp: Components/STUHealthComponent.cpp

1// OnTakeAnyDamage
2if (IsDead())
3{
4    OnDeath.Broadcast();
5}

STUBaseCharacter注册委托服务: OnDeath

-
仅C++ AddUObject

搭建框架: 注册死亡通知

  1. 添加空函数

    ShootThemUp: Player/STUBaseCharacter.cpp
    1void ASTUBaseCharacter::OnDeath() {}     
    
  2. 注册委托服务

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// BeginPlay
    2HealthComponent->OnDeath.AddUObject(this, &ASTUBaseCharacter::OnDeath);            
    
  3. 函数声明

    private

    ShootThemUp: Player/STUBaseCharacter.h

实现处理函数OnDeath

  1. 添加销毁延时

    protected

    ShootThemUp: Player/STUBaseCharacter.h
    1UPROPERTY(EditDefaultsOnly, meta = (ClampMin = "0.0", ClampMax = "10.0"))
    2float LifeSpanOnDeath = 5.0f;
  2. 检查CharacterMovement组件有效性

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// BeginPlay
    2check(GetCharacterMovement());
  3. 剥夺玩家对游戏角色的控制权, 开启定时器销毁Character

    ShootThemUp: Player/STUBaseCharacter.cpp
    1// OnDeath
    2GetCharacterMovement()->DisableMovement();
    3SetLifeSpan(LifeSpanOnDeath);

创建死亡动画剪辑

虚幻编辑器

之前的跳跃、跑步、转向动画, 均对应状态机中的一个状态. 如果游戏角色死亡拥有对应状态, 每个状态都可能迁移到死亡状态, 光是想想都觉得麻烦

使用动画剪辑 AnimMontage 资产, 当游戏角色死亡时, 播放死亡动画剪辑, 通过slot连接当前动画和死亡动画剪辑


创建AnimMontage资产

-
死亡动画资产 ExternalContent/Animation/Animations/TTP_Animations/Death
  1. 选中死亡动画资产, 右键 > Create > Create AnimMontage > 命名为AM_Death


  2. 移动到Content/Player/Animations路径下



在动画蓝图中添加Slot

ABP_BaseCharacter > AnimGraph


在Locomotion和OutputPose之间添加Slot



Slot和AM_Death的分组一致

  1. Slot

    -
    SlotName DefaultGroup.DefaultSlot


  2. AM_Death

    -
    Montage DefaultGroup.DefaultSlot



设置动画剪辑

AM_Death

死亡动画结束后, 不再播放其他动画

Asset Details > BlendOptions > EnableAutoBlendOut, 取消勾选



游戏角色死亡时, 播放动画剪辑

C++

C++类型
动画剪辑 AnimMontage UAnimMontage

添加UAnimMontage类型数据成员

protected

ShootThemUp: Player/STUBaseCharacter.h

1UPROPERTY(EditDefaultsOnly)
2UAnimMontage *DeathAnimMontage;

Character死亡时, 播放动画剪辑

ShootThemUp: Player/STUBaseCharacter.cpp

1// OnDeath
2PlayAnimMontage(DeathAnimMontage);

查看

虚幻编辑器

  1. 设置游戏角色死亡时播放的动画剪辑

    BP_STUBaseCharacter


  2. 效果图


    禁止移动Character之后, 销毁Character之前, 仍可以移动Camera;即, 水平旋转视角时可以旋转Character