在这一篇文章里,我们实现一下技能描述,我们有两个技能描述的框,一个显示当前技能的描述,另一个显示下一级技能的描述。
对于技能的描述,里面会有很多的样式,正常情况下我们是无法创建这么多对面的UI节点,所以,我们需要使用的是,富文本框,在UE里翻译是多格式文本块。
对于做过前端的小伙伴这个应该熟悉,那么接下来,我们实现一下显示。
添加富文本样式
我们需要使用多格式文本块来显示
将其添加到滚动框内
并将其设置为变量,方便后续使用逻辑修改显示内容
接下来,我们要创建富文本的样式,需要使用数据表格来实现DataTable
结构使用RichTextStyleRow
创建完成,我们添加一行
可以设置对应的文字样式
接着,我们修改文字使用的字体,大小颜色等内容
并在多格式文本块上面应用使用此表格
接着创建文本,我们需要使用<Name></>
这种方式来实现设置样式应用的范围,学过html的小伙伴应该最熟悉了
然后查看样式
注意,你修改后,需要编译,才能查看效果
这是我们添加了两个格式后的效果
如果你设置了Default项的样式,如果没有设置标签的文字,将默认使用Default样式来设置文本。
我们添加多个需要设置的格式,对应内容使用对应的格式。
接着测试效果即可。
添加技能描述委托
现在,我们创建了可以显示技能描述的UI,接下来,我们在点击技能按钮以后,或者升级技能或降级技能时,技能描述能够根据状态去修改对应的描述,所以,我们需要在技能类里实现获取当前等级的技能描述,并在UI上展示出来。
我们在RPGGameplayAbility.h里增加三个函数,用于获取技能的描述,分别是,当前等级的技能描述,下一等级的技能描述,锁定技能的描述。
virtual FString GetDescription(int32 Level); //获取当前等级的技能描述
virtual FString GetNextLevelDescription(int32 Level); //获取技能下一等级的技能描述
static FString GetLockedDescription(int32 Level); //获取锁定技能描述
接着在cpp文件里实现函数,这里有个注意点,就是如果你使用字符串,需要在字符串前面增加一个L
FString URPGGameplayAbility::GetDescription(int32 Level)
{
return FString::Printf(TEXT("%s, <Level>%d</>"), L"默认技能名称 - 火球术火球术火球术火球术", Level);
}
FString URPGGameplayAbility::GetNextLevelDescription(int32 Level)
{
return FString::Printf(TEXT("下一等级:<Level>%d</> 造成更多的伤害。"), Level);
}
FString URPGGameplayAbility::GetLockedDescription(int32 Level)
{
return FString::Printf(TEXT("技能将在角色等级达到<Level>%d</>时解锁"), Level);
}
如果你不增加,会提示格式不正确
接着我们在RPGAbilitySystemComponent.h文件里增加一个函数,用于通过技能标签获取技能描述
bool GetDescriptionByAbilityTag(const FGameplayTag& AbilityTag, FString& OutDescription, FString& OutNextLevelDescription); //通过标签获取技能描述
在实现这里,我们使用了引用的方式,可以实现函数修改外部创建的变量的值。如果传入的技能标签无法获取到对于的技能实例,我们将返回锁定技能的描述,如果获取得到,我们将通过实例获取到技能类,并通过类的函数去获取技能描述。
bool URPGAbilitySystemComponent::GetDescriptionByAbilityTag(const FGameplayTag& AbilityTag, FString& OutDescription, FString& OutNextLevelDescription)
{
//如果当前技能处于锁定状态,将无法获取到对应的技能描述
if(FGameplayAbilitySpec* AbilitySpec = GetSpecFromAbilityTag(AbilityTag))
{
if(URPGGameplayAbility* RPGAbility = Cast<URPGGameplayAbility>(AbilitySpec->Ability))
{
OutDescription = RPGAbility->GetDescription(AbilitySpec->Level);
OutNextLevelDescription = RPGAbility->GetNextLevelDescription(AbilitySpec->Level + 1);
return true;
}
}
//如果技能是锁定状态,将显示锁定技能描述
UAbilityInfo* AbilityInfo = URPGAbilitySystemBlueprintLibrary::GetAbilityInfo(GetAvatarActor());
OutDescription = URPGGameplayAbility::GetLockedDescription(AbilityInfo->FindAbilityInfoForTag(AbilityTag).LevelRequirement);
OutNextLevelDescription = FString();
return false;
}
接着,我们在技能面板里定义一个新的委托类型,专门用于广播技能描述
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSpellDescriptionSignature, FString, SpellDescription, FString, SpellNextLevelDescription); //技能描述委托
并在类里添加一个委托变量
UPROPERTY(BlueprintAssignable)
FSpellDescriptionSignature SpellDescriptionSignature; //选中技能按钮后,技能和下一级描述委托
在我们之前实现的BroadcastSpellGlobeSelected函数里,添加委托的广播,这个函数会在鼠标点击技能按钮函数,以及在技能状态修改和技能点变动时被调用。
void USpellMenuWidgetController::BroadcastSpellGlobeSelected()
{
bool bEnableSpendPoints = false; //技能是否可以升级
bool bEnableEquip = false; //技能是否可以装配
bool bEnableDemotion = false; //技能是否可以降级
ShouldEnableButtons(SelectedAbility.Status, CurrentSpellPoints > 0, bEnableSpendPoints, bEnableEquip, bEnableDemotion); //获取结果
SpellGlobeSelectedSignature.Broadcast(bEnableSpendPoints, bEnableEquip, bEnableDemotion, SelectedAbility.Level); //广播状态
//广播技能描述
FString Description;
FString NextLevelDescription;
GetRPGASC()->GetDescriptionByAbilityTag(SelectedAbility.Ability, Description, NextLevelDescription);
SpellDescriptionSignature.Broadcast(Description, NextLevelDescription);
}
编译打开蓝图,我们在技能UI蓝图里,绑定对当前描述委托的监听,设置技能的文本。
为了保证能够自动换行,我们需要设置自动包裹文本,英文为 auto warp text更贴切
接着,我们运行查看效果
然后点击被锁定的技能查看