这一篇的目的是实现生命值与UI的交互,即角色的Health发生改变后,UI的血条也会发生相应的改变。为了实现这个目的,我们需要有以下几个步骤:
- 初始化AttributeSet,之前角色的属性值是没有初始化的,是从0开始的
- 通过Delegate,将HealthAttribute和CharacterBase.cpp中的处理生命变化的函数bind在一起。
- 实现角色的生命值UI。
OK,进入正题。
初始化AttributeSet
我个人认为初始化Attributes的较好的方法有两种,一是通过Gameplay Effect,在角色蓝图中的BeginPlay初始化角色的属性值。二是通过datatable,在ability system component中初始化属性值。
首先尝试第一种方法。
新建一个Gameplay Effect命名为GE_AttributeDefault。Modifier设置如下,override Health,修改为100。
在beginplay中通过ApplyGameplayEffectToSelf赋初值。
然后是第二种方法。
第二种方法通过DataTable初始化属性集
结构选择AttributeMetaData
然后数据为
在角色蓝图中的Ability System Component设置里,将Attribute和DataTable添加上去。
修改一下之前的测试内容
开始游戏,攻击,可以看到角色的初始生命值变成100了。
通过Delegate通知生命值被修改
打开rider(感觉比VS好用多了)。在CharacterBase.h中添加delagte。然后建一个函数,负责Broadcast这个delegate。
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangeEvent, float, NewHealth);
UCLASS()
class GAS_LEARN_API ACharacterBase : public ACharacter, public IAbilitySystemInterface
{
// ......
// Attribute update function
UPROPERTY(BlueprintAssignable, Category="Ability")
FOnHealthChangeEvent HealthChangeEvent;
void OnHealthAttributeChanged(const FOnAttributeChangeData& Data);
};
复制代码
打开CharacterBase.cpp,实现function
void ACharacterBase::OnHealthAttributeChanged(const FOnAttributeChangeData& Data)
{
HealthChangeEvent.Broadcast(Data.NewValue);
}
复制代码
在BeginPlay中将OnHealthAttributeChanged function与AbilitySystem中的Attribute Bind。
// Called when the game starts or when spawned
void ACharacterBase::BeginPlay()
{
Super::BeginPlay();
if(AbilitySystem)
{
AbilitySystem->GetGameplayAttributeValueChangeDelegate(UAttributeSetBase::GetHealthAttribute())
.AddUObject(this, &ACharacterBase::OnHealthAttributeChanged);
}
}
复制代码
实现Health的UI
新建Widget,命名为W_HealthUI,然后新建ProgressBar,命名为HealthBar,然后调整一下颜色和percent,可以弄成自己喜欢的粉红色。
然后新建Custom Event,用来修改HealthBar的Percent
然后打开角色蓝图,添加Widget Component
然后在BeginPlay中将Health Change的与自己的CustomEvent绑定,用来修改HealthUI中HealthBar的Percent
完成。
测试
运行游戏,对着假人攻击,可以看到扣血了,Health Attribute与UI的交互完成。