网站验证码是如何做的,为什么自己做的网站别人打不开,oss可以做网站根目录吗,wordpress 开源地图插件在上一篇介绍了对标签如何在项目中设置#xff0c;这一篇先讲解一下如何在GE里面使用GameplayTag标签。 之前我在第十一章节中 11. UE5 RPG使用GameplayEffect修改角色属性#xff08;二#xff09;介绍了一些GE的属性#xff0c;在UE 5.3版本中#xff0c;修改的配置方式…在上一篇介绍了对标签如何在项目中设置这一篇先讲解一下如何在GE里面使用GameplayTag标签。 之前我在第十一章节中 11. UE5 RPG使用GameplayEffect修改角色属性二介绍了一些GE的属性在UE 5.3版本中修改的配置方式需要在组件里面设置需要的组件 下图为与标签相关的组件
查看当前actor拥有的标签
首先我们在一个用于持续性时间的GE上面添加一个标签比如我在一个回血的GE上面添加了一个Health的标签 然后运行游戏按~建打开debug 左上角会显示当前actor拥有的标签当前actor是没有任何标签的 在应用了对应的GE后会发现角色身上多出了对应的标签在GE效果消失后对应的标签也被剔除。后面的括号内的数值代表当前添加的数量它也可以被堆叠。注意通过GE堆叠的方式是无法让标签产生堆叠的。如果设置不堆叠每个是单独的GE那么会出现标签堆叠的效果。
ASC使用委托监听GE
接下来我们要实现GE被应用时使用委托触发回调进行其它处理 翻看ASC.h的源码会发现有相应的委托代码委托返回ASCGE的实例GE的引用三个参数 接着往下看会发现基于这个委托宏创建了多个委托属性有添加GE给自身触发的有添加给目标触发的有持续时间的GE添加给自身触发的还有周期性触发的GE的委托等等。
鼠标悬停到属性上面也能够查看到对应的返回 接下来我们要实现的就是绑定委托在给自身添加GE时打印GE附加的Asset Tag
在AbilitySystemComponentBase 技能组件基类里面我们添加一个AbilityActorInfoSet()函数这个函数用于初始化委托的注册。 然后添加一个委托触发的回调函数EffectApplied()这个函数将在GE被添加的时候触发。
// 版权归暮志未晚所有。#pragma once#include CoreMinimal.h
#include AbilitySystemComponent.h
#include AbilitySystemComponentBase.generated.h/*** 技能系统组件*/
UCLASS()
class AURA_API UAbilitySystemComponentBase : public UAbilitySystemComponent
{GENERATED_BODY()public:void AbilityActorInfoSet();protected:void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle);
};
在cpp中我们将对其进行实现AbilityActorInfoSet()中先绑定了一个GE添加到自身的委托事件触发时将调用EffectApplied()函数EffectApplied()函数内现在将获取到GE身上的AssetTags并通过遍历的形式打印出来。
// 版权归暮志未晚所有。#include AbilitySystem/AbilitySystemComponentBase.hvoid UAbilitySystemComponentBase::AbilityActorInfoSet()
{OnGameplayEffectAppliedDelegateToSelf.AddUObject(this, UAbilitySystemComponentBase::EffectApplied);
}void UAbilitySystemComponentBase::EffectApplied(UAbilitySystemComponent* AbilitySystemComponent,const FGameplayEffectSpec EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle)
{// GEngine-AddOnScreenDebugMessage(1, 8.f, FColor::Blue, FString(Effect Applied!));FGameplayTagContainer TagContainer;EffectSpec.GetAllAssetTags(TagContainer);for(const FGameplayTag Tag : TagContainer){//TODO: 将tag广播给Widget Controllerconst FString Msg FString::Printf(TEXT(GE Tag: %s), *Tag.ToString()); //获取Asset TagGEngine-AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, Msg); //打印到屏幕上 -1 不会被覆盖}
}
ASC的基础类添加了我们还需要对其进行调用事件委托的绑定需要在ASC初始化完成后调用。
在所有的角色基类上面我们添加一个virtual void InitAbilityActorInfo();这个函数用于初始化ASC的委托注册下面为初始化的代码
CastUAbilitySystemComponentBase(AbilitySystemComponent)-AbilityActorInfoSet();在基类上我们不去做实现实现在英雄类和敌人类里面去实现。
在英雄类里面在原来的基础上初始化ASC后进行调用
void AHeroCharacter::PossessedBy(AController* NewController)
{Super::PossessedBy(NewController);//初始化ASC的OwnerActor和AvatarActorInitAbilityActorInfo();//设置OwnerActor的ControllerSetOwner(NewController);
}void AHeroCharacter::OnRep_PlayerState()
{Super::OnRep_PlayerState();//初始化ASC的OwnerActor和AvatarActorInitAbilityActorInfo();
}void AHeroCharacter::InitAbilityActorInfo()
{APlayerStateBase* PlayerStateBase GetPlayerStateAPlayerStateBase();check(PlayerStateBase); //检测是否有效无限会暂停游戏//从playerState获取ASC和ASAbilitySystemComponent PlayerStateBase-GetAbilitySystemComponent();AttributeSet PlayerStateBase-GetAttributeSet();//初始化ASCAbilitySystemComponent-InitAbilityActorInfo(PlayerStateBase, this);//触发Actor的技能信息设置回调CastUAbilitySystemComponentBase(AbilitySystemComponent)-AbilityActorInfoSet(); //获取PCif(APlayerControllerBase* PlayerControllerBase CastAPlayerControllerBase(GetController())){if(AMyHUD* HUD CastAMyHUD(PlayerControllerBase-GetHUD())){HUD-InitOverlay(PlayerControllerBase, PlayerStateBase, AbilitySystemComponent, AttributeSet);}}}在敌人类里面初始化委托方式一致
void AEnemyBase::BeginPlay()
{Super::BeginPlay();InitAbilityActorInfo();
}void AEnemyBase::InitAbilityActorInfo()
{AbilitySystemComponent-InitAbilityActorInfo(this, this);CastUAbilitySystemComponentBase(AbilitySystemComponent)-AbilityActorInfoSet();
}在初始化完成后我们在UE里面的GE添加AssetTagsGameplayEffectComponent并且添加对应的Tags测试应用时是否有打印。
使用委托将ASC和Widget Controller绑定
上面我们实现了获取添加GE时的回调并能够打印对应GE上面添加的Tags接下来我们要实现ASC和Widget Controller之间的沟通在GE添加时在WidgetController里面也能够获取到Broadcast广播并触发对应的回调。
ASC.h在之前的基础上添加一个委托宏设置FEffectAssetTags然后定义一个属性EffectAssetTags用于后续的广播。
// 版权归暮志未晚所有。#pragma once#include CoreMinimal.h
#include AbilitySystemComponent.h
#include AbilitySystemComponentBase.generated.hDECLARE_MULTICAST_DELEGATE_OneParam(FEffectAssetTags, const FGameplayTagContainer /* AssetTags */)/*** 技能系统组件*/
UCLASS()
class AURA_API UAbilitySystemComponentBase : public UAbilitySystemComponent
{GENERATED_BODY()public:void AbilityActorInfoSet();FEffectAssetTags EffectAssetTags;protected:void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle);
};
在cpp里EffectApplied是添加GE后的事件回调之前我们是直接在这里打印的tags现在我们修改成获取到TagContainer后将TagContainer进行委托广播出去。
// 版权归暮志未晚所有。#include AbilitySystem/AbilitySystemComponentBase.hvoid UAbilitySystemComponentBase::AbilityActorInfoSet()
{OnGameplayEffectAppliedDelegateToSelf.AddUObject(this, UAbilitySystemComponentBase::EffectApplied);
}void UAbilitySystemComponentBase::EffectApplied(UAbilitySystemComponent* AbilitySystemComponent,const FGameplayEffectSpec EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle)
{// GEngine-AddOnScreenDebugMessage(1, 8.f, FColor::Blue, FString(Effect Applied!));FGameplayTagContainer TagContainer;EffectSpec.GetAllAssetTags(TagContainer);EffectAssetTags.Broadcast(TagContainer);
}
之前我们制作的先初始化ASC完成以后然后通过HUD类对Widget用户控件初始化然后再对Widget Controller初始化的。所以在初始化Widget Controller时ASC是初始化完成的。 我们在Widget Controller绑定事件委托里面添加对ASC的委托EffectAssetTags进行监听即可。
以下是用户控件使用的Widget Controller的初始化委托监听的函数前面的是之前监听AS属性值变化的代码后面我们通过AddLambda添加了一个匿名函数用于监听EffectAssetTags并在里面进行测试打印。
void UOverlayWidgetController::BindCallbacksToDependencies()
{const UAttributeSetBase* AttributeSetBase CastCheckedUAttributeSetBase(AttributeSet);AbilitySystemComponent-GetGameplayAttributeValueChangeDelegate(AttributeSetBase-GetHealthAttribute()).AddUObject(this, UOverlayWidgetController::HealthChanged);AbilitySystemComponent-GetGameplayAttributeValueChangeDelegate(AttributeSetBase-GetMaxHealthAttribute()).AddUObject(this, UOverlayWidgetController::MaxHealthChanged);AbilitySystemComponent-GetGameplayAttributeValueChangeDelegate(AttributeSetBase-GetManaAttribute()).AddUObject(this, UOverlayWidgetController::ManaChanged);AbilitySystemComponent-GetGameplayAttributeValueChangeDelegate(AttributeSetBase-GetMaxManaAttribute()).AddUObject(this, UOverlayWidgetController::MaxManaChanged);//AddLambda 绑定匿名函数CastUAbilitySystemComponentBase(AbilitySystemComponent)-EffectAssetTags.AddLambda([](const FGameplayTagContainer AssetTags){for(const FGameplayTag Tag : AssetTags){//将tag广播给Widget Controllerconst FString Msg FString::Printf(TEXT(GE Tag in Widget Controller: %s), *Tag.ToString()); //获取Asset TagGEngine-AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, Msg); //打印到屏幕上 -1 不会被覆盖}});
}接着运行代码发现左上角打印了对应的tags代表代码无误。
创建标签消息委托
上面我们实现了可以在添加GE的时候打印GE身上的Tag接下来将实现在Widget里面通过委托获取GE的应用标签。
首先在WidgetController里面创建一个结构体这个结构体可以被蓝图使用。 结构体内主要存储一些数据用于在ui上面展示使用所以我们需要GE的信息Tag提示文本信息使用的Widget控件以及显示的图片都存储到结构体内。
USTRUCT(BlueprintType)
struct FUIWidgetRow : public FTableRowBase
{GENERATED_BODY();UPROPERTY(EditAnywhere, BlueprintReadOnly)FGameplayTag MessageTag FGameplayTag();UPROPERTY(EditAnywhere, BlueprintReadOnly)FText Message FText();UPROPERTY(EditAnywhere, BlueprintReadOnly)TSubclassOfclass UMyUserWidget MessageWidget;UPROPERTY(EditAnywhere, BlueprintReadOnly)UTexture2D* Image nullptr;
};编译后创建一个数据表格类就选择我们创建的结构体。 接下来我们要实现数据使用的内容首先创建信息Tag在GameplayTag标签管理器里面添加信息标签。 到现在我们还没有创建Widget显示控件先把别的内容填上 接下来在WidgetController上面增加一个配置项用于配置数据 //EditDefaultsOnly 说明此属性可以通过属性窗口编辑但只能在原型上进行。UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, CategoryWidget Data)TObjectPtrUDataTable MessageWidgetDataTable;将刚才创建的数据表格设置 接着创建一个可以通过Tag在数据表格中寻找对应的数据的函数为了兼容不同的数据表格这里我们使用不确定的T类型在调用时指定返回类型。 //根据传入的表格和Tag返回查找到的数据表格类型不确定所以使用T来表示在使用此函数时需要指定对应类型templatetypename TT* GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag Tag);template typename T
T* UOverlayWidgetController::GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag Tag)
{T* Row DataTable-FindRowT(Tag.GetTagName(), TEXT());return Row;
}在之前我们实现的匿名函数里面首先添加的GE内是否包含Message的Tag如果包含则广播出去。 //AddLambda 绑定匿名函数CastUAbilitySystemComponentBase(AbilitySystemComponent)-EffectAssetTags.AddLambda([this](const FGameplayTagContainer AssetTags) //中括号添加this是为了保证内部能够获取类的对象{for(const FGameplayTag Tag : AssetTags){//对标签进行检测如果不是信息标签将无法进行广播FGameplayTag MessageTag FGameplayTag::RequestGameplayTag(FName(Message));// A.1.MatchesTag(A) will return True, A.MatchesTag(A.1) will return Falseif(Tag.MatchesTag(MessageTag)){FUIWidgetRow* Row GetDataTableRowByTagFUIWidgetRow(MessageWidgetDataTable, Tag);MessageWidgetRowDelegate.Broadcast(*Row); //前面加*取消指针引用}}});代码逻辑基本实现到这然后我们需要在药瓶的GE里面添加Tag 然后做一个测试在Widget中先将Controller类型转换为OverlayWidgetController 接着监听数据返回打印信息 数据能够打印证明准确无误
创建信息Widget
结构体内我们还有一项没有实现那就是Widget组件接下来我们将实现这个组件。 首先创建一个用户控件基类就使用我们之前实现的基类 在Widget里面创建一个显示图片和文本的对象组件。 如果以水平框作为最外层会被父节点拉伸我们可以使用一个覆层包裹一下。
图表里面增加一个设置图片和文本的蓝图函数。 创建完成我们可以将数据表格的数据填充上去对于的Widget
接下来我们就可以修改Overlay的debug的蓝图不用再打印文本而是直接添加widget到视口。 下图为修改后的蓝图节点我们使用数据创建一个widget并设置显示在屏幕中间 接下来我们给widget制作了一个新的动画并添加到了设置函数上面在设置完成属性后播放动画 播放动画后面的执行是直接执行的不是在动画播放完成执行所以我们需要制作一个事件在延迟动画的时间后销毁掉并在销毁回调中测试 在测试捡起药瓶后检查动画是否播放完成回调是否触发这样不会造成内存溢出。