六一的部落格


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




说明

  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