P48-56 应用游戏标签
这一段课主要是把每种道具的游戏Tag进行了整理与应用
AuraAbilitySystemComponentBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "AbilitySystemComponent.h" #include "AuraAbilitySystemComponentBase.generated.h" DECLARE_MULTICAST_DELEGATE_OneParam(FEffectAssTags, const FGameplayTagContainer& /*AssetTags*/) /** * */ UCLASS() class MYGAS_API UAuraAbilitySystemComponentBase : public UAbilitySystemComponent { GENERATED_BODY() protected: void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec& GameplayEffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle); public: void AbilityActorInfoSet(); FEffectAssTags EffectAssetTags; };
AuraAbilitySystemComponentBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "AbilitySystem/AuraAbilitySystemComponentBase.h" void UAuraAbilitySystemComponentBase::AbilityActorInfoSet() { OnGameplayEffectAppliedDelegateToSelf.AddUObject(this,&UAuraAbilitySystemComponentBase::EffectApplied); } void UAuraAbilitySystemComponentBase::EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec& GameplayEffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle) { FGameplayTagContainer TagContainer; GameplayEffectSpec.GetAllAssetTags(TagContainer); EffectAssetTags.Broadcast(TagContainer); }
AuraEffectActor.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameplayEffect.h" #include "AbilitySystem/AuraAbilitySystemComponentBase.h" #include "Components/SphereComponent.h" #include "GameFramework/Actor.h" #include "GameplayEffectTypes.h" #include "AuraEffectActor.generated.h" class UGameplayEffect; class UAbilitySystemComponent; UENUM(BlueprintType) enum class EEffectApplicationPolicy : uint8 { ApplyOnOverlap,ApplyOnEndOverlap,DoNotApply }; UENUM(BlueprintType) enum class EEffectRemovePolicy : uint8 { RemoveOnEndOverlap,DoNotRemove }; UCLASS() class MYGAS_API AAuraEffectActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AAuraEffectActor(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UFUNCTION(BlueprintCallable) void ApplyEffectToTarget(AActor* TargetActor, TSubclassOf<UGameplayEffect> GameplayEffectClass); UFUNCTION(BlueprintCallable) void OnOverlap(AActor* TargetActor); UFUNCTION(BlueprintCallable) void OnEndOverlap(AActor* TargetActor); UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") TSubclassOf<UGameplayEffect> InstantGameplayEffectClass; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") EEffectApplicationPolicy InstantEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") TSubclassOf<UGameplayEffect> DurationGameplayEffectClass; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") EEffectApplicationPolicy DurationEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") TSubclassOf<UGameplayEffect> InfiniteGameplayEffectClass; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") EEffectApplicationPolicy InfiniteEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") EEffectRemovePolicy InfiniteEffectRemovePolicy = EEffectRemovePolicy::RemoveOnEndOverlap; TMap<FActiveGameplayEffectHandle , UAbilitySystemComponent*> ActiveEffectHandles; UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Applied Effects") float ActorLevel = 1.f; private: };
AuraEffectActor.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Actor/AuraEffectActor.h" #include "AbilitySystemBlueprintLibrary.h" #include "AbilitySystemComponent.h" #include "AbilitySystemInterface.h" #include "AbilitySystem/AuraAbilitySystemComponentBase.h" #include "AbilitySystem/AuraAttributeSet.h" #include "Components/StaticMeshComponent.h" // Sets default values AAuraEffectActor::AAuraEffectActor() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = false; SetRootComponent(CreateDefaultSubobject<USceneComponent>("SceneRoot")); } // Called when the game starts or when spawned void AAuraEffectActor::BeginPlay() { Super::BeginPlay(); } void AAuraEffectActor::ApplyEffectToTarget(AActor* TargetActor, TSubclassOf<UGameplayEffect> GameplayEffectClass) { //这里是使用 UAbilitySystemBlueprintLibrary 内的静态函数,在指定的Target上查找并返回UAbilitySystemComponent UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor); if(TargetASC==nullptr) return; check(GameplayEffectClass); //创建了一个游戏效果的内容句柄,提供游戏效果的信息 FGameplayEffectContextHandle TargetASCContext =TargetASC->MakeEffectContext(); //把自己作为游戏效果的源对象,确保AbilitySystem可以识别到自己 TargetASCContext.AddSourceObject(this); //这里创建了一个游戏效果规范,GameplayEffectClass 是要应用的游戏效果的类,1.0f 是游戏效果的初始生命周期倍率,TargetASCContext 是游戏效果的上下文. 调用 MakeOutgoingSpec 函数,将会根据提供的参数创建一个游戏效果规范 const FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass,ActorLevel,TargetASCContext); const FActiveGameplayEffectHandle ActiveGameplayEffectHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get()); const bool bIsInfinite = EffectSpecHandle.Data.Get()->Def.Get()->DurationPolicy == EGameplayEffectDurationType::Infinite; if(bIsInfinite) { ActiveEffectHandles.Add(ActiveGameplayEffectHandle,TargetASC); } } void AAuraEffectActor::OnOverlap(AActor* TargetActor) { if(InstantEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap) { ApplyEffectToTarget(TargetActor,InstantGameplayEffectClass); } if(DurationEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap) { ApplyEffectToTarget(TargetActor,DurationGameplayEffectClass); } if(InfiniteEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap) { ApplyEffectToTarget(TargetActor,InfiniteGameplayEffectClass); } } void AAuraEffectActor::OnEndOverlap(AActor* TargetActor) { if(InstantEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap) { ApplyEffectToTarget(TargetActor,InstantGameplayEffectClass); } if(DurationEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap) { ApplyEffectToTarget(TargetActor,DurationGameplayEffectClass); } if(InfiniteEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap) { ApplyEffectToTarget(TargetActor,InfiniteGameplayEffectClass); } if(InfiniteEffectRemovePolicy == EEffectRemovePolicy::RemoveOnEndOverlap) { //获取到目标角色的能力组件 UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor); if(!IsValid(TargetASC)) return; //创建了一个储存移除游戏效果句柄的数组 HandlesToRemove TArray<FActiveGameplayEffectHandle> HandlesToRemove; //遍历 ActiveEffectHandles 数组 for(TTuple<FActiveGameplayEffectHandle, UAbilitySystemComponent*> HandlePair:ActiveEffectHandles) { // 当 TargetASC 内有 HandlePair.Value的值的时候 if(TargetASC == HandlePair.Value) { // 移除 HandlePair 的效果 TargetASC->RemoveActiveGameplayEffect(HandlePair.Key, 1); //把这个效果放在 HandlesToRemove 中 HandlesToRemove.Add(HandlePair.Key); } } // 遍历 HandlesToRemove 内的每一个元素 for(auto& Handle : HandlesToRemove) { // 在 ActiveEffectHandles 这个数组内移除 ActiveEffectHandles.FindAndRemoveChecked(Handle); } } }
AuraCharacter.h
private: virtual void InitAbilityActorInfo() override;
AuraCharacter.cpp
void AAuraCharacter::InitAbilityActorInfo() { AAuraPlayerState* AuraPlayerState = GetPlayerState<AAuraPlayerState>(); check(AuraPlayerState); AuraPlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(AuraPlayerState,this); Cast<UAuraAbilitySystemComponentBase>(AuraPlayerState->GetAbilitySystemComponent())->AbilityActorInfoSet(); AbilitySystemComponent = AuraPlayerState->GetAbilitySystemComponent(); AttributesSet = AuraPlayerState->GetAttributeSet(); //当角色初始化的时候加载UI的初始化 if(AAuraPlayerController* AuraPlayerController = Cast<AAuraPlayerController>(GetController())) { //获得HUD AAuraHUD* AuraHUD = Cast<AAuraHUD>(AuraPlayerController->GetHUD()); AuraHUD->InitOverlay(AuraPlayerController,AuraPlayerState,AbilitySystemComponent,AttributesSet); } }
AuraCharacterBase.h
virtual void InitAbilityActorInfo();
AuraCharacterBase.cpp
void AAuraCharacterBase::InitAbilityActorInfo() { }
AuraEnemy.h
protected: virtual void BeginPlay() override; virtual void InitAbilityActorInfo() override; };
AuraEnemy.cpp
void AAuraEnemy::BeginPlay() { Super::BeginPlay(); InitAbilityActorInfo(); } void AAuraEnemy::InitAbilityActorInfo() { AbilitySystemComponent->InitAbilityActorInfo(this,this); Cast<UAuraAbilitySystemComponentBase>(AbilitySystemComponent)->AbilityActorInfoSet(); }
OverlayAuraWidgetController.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "IPropertyTable.h" #include "UI/WidgetController/AuraWidgetController.h" #include "OverlayAuraWidgetController.generated.h" USTRUCT(BlueprintType) struct FUIWidgetRow : public FTableRowBase { GENERATED_BODY() UPROPERTY(EditAnywhere,BlueprintReadOnly) FGameplayTag MessageTag = FGameplayTag(); UPROPERTY(EditAnywhere,BlueprintReadOnly) FText Message = FText(); UPROPERTY(EditAnywhere,BlueprintReadOnly) TSubclassOf<class UAuraUserWidget> MessageWidget; UPROPERTY(EditAnywhere,BlueprintReadOnly) UTexture2D* Image = nullptr; }; class UAuraUserWidget; DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature, float, NewHealth); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxHealthChangedSignature,float,NewMaxHealth); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnManaChangedSignature,float,NewMana); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxManaChangedSignature,float,NewMaxMana); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMessageWidgetRowSingnature, FUIWidgetRow, Row); /** * */ UCLASS(BlueprintType,Blueprintable) class MYGAS_API UOverlayAuraWidgetController : public UAuraWidgetController { GENERATED_BODY() public: virtual void BroadcastInitialValues() override; virtual void BindCallbacksToDependencies() override; UPROPERTY(BlueprintAssignable,Category="GAS|Attributes") FOnHealthChangedSignature OnHealthChangedSignature; UPROPERTY(BlueprintAssignable,Category="GAS|Attributes") FOnMaxHealthChangedSignature OnMaxHealthChangedSignature; UPROPERTY(BlueprintAssignable,Category="GAS|Attributes") FOnManaChangedSignature OnManaChangedSignature; UPROPERTY(BlueprintAssignable,Category="GAS|Attributes") FOnMaxManaChangedSignature OnMaxManaChangedSignature; UPROPERTY(BlueprintAssignable,Category="GAS|Messages") FMessageWidgetRowSingnature MessageWidgetRowDelegate; protected: UPROPERTY(EditDefaultsOnly,BlueprintReadOnly,Category="Widget Data") TObjectPtr<UDataTable> MessageWidgetDataTable; void HealthChanged(const FOnAttributeChangeData& Data) const; void MaxHealthChanged(const FOnAttributeChangeData& Data) const; void ManaChanged(const FOnAttributeChangeData& Data) const; void MaxManaChanged(const FOnAttributeChangeData& Data) const; template<typename T> T* GetDataTableRowByTag(UDataTable* DataTable,const FGameplayTag& Tag); }; template <typename T> T* UOverlayAuraWidgetController::GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag& Tag) { return DataTable->FindRow<T>(Tag.GetTagName(), TEXT(""));; }
OverlayAuraWidgetController.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "UI/WidgetController/OverlayAuraWidgetController.h" #include "AbilitySystem/AuraAbilitySystemComponentBase.h" #include "AbilitySystem/AuraAttributeSet.h" #include "Engine/Engine.h" #include "GameFramework/Pawn.h" class UAuraAttributeSet; void UOverlayAuraWidgetController::BroadcastInitialValues() { //这里应该绑定一个事件,获取到AuraAttributeSet const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet); // 获取到 Health 和 MaxHealth 属性,并进行广播 OnHealthChangedSignature.Broadcast(AuraAttributeSet->GetHealth()); OnMaxHealthChangedSignature.Broadcast(AuraAttributeSet->GetMaxHealth()); OnManaChangedSignature.Broadcast(AuraAttributeSet->GetMana()); OnMaxManaChangedSignature.Broadcast(AuraAttributeSet->GetMaxMana()); } void UOverlayAuraWidgetController::BindCallbacksToDependencies() { const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet); //绑定血量 AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate( AuraAttributeSet->GetHealthAttribute()).AddUObject(this,&UOverlayAuraWidgetController::HealthChanged); AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate( AuraAttributeSet->GetMaxHealthAttribute()).AddUObject(this,&UOverlayAuraWidgetController::MaxHealthChanged); //绑定蓝量 AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate( AuraAttributeSet->GetManaAttribute()).AddUObject(this,&UOverlayAuraWidgetController::ManaChanged); AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate( AuraAttributeSet->GetMaxManaAttribute()).AddUObject(this,&UOverlayAuraWidgetController::MaxManaChanged); Cast<UAuraAbilitySystemComponentBase>(AbilitySystemComponent)->EffectAssetTags.AddLambda( [this](const FGameplayTagContainer& AssetTags) { for(const FGameplayTag& Tag : AssetTags) { //检查 MessageTag 是否是Data表内的 MessageTag,如何不是就会返回False FGameplayTag MessageTag = FGameplayTag::RequestGameplayTag(FName("Message")); if(Tag.MatchesTag(MessageTag)) { const FUIWidgetRow* Row = GetDataTableRowByTag<FUIWidgetRow>(MessageWidgetDataTable , Tag); MessageWidgetRowDelegate.Broadcast(*Row); } } } ); } void UOverlayAuraWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const { OnHealthChangedSignature.Broadcast(Data.NewValue); } void UOverlayAuraWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const { OnMaxHealthChangedSignature.Broadcast(Data.NewValue); } void UOverlayAuraWidgetController::ManaChanged(const FOnAttributeChangeData& Data) const { OnManaChangedSignature.Broadcast(Data.NewValue); } void UOverlayAuraWidgetController::MaxManaChanged(const FOnAttributeChangeData& Data) const { OnMaxManaChangedSignature.Broadcast(Data.NewValue); }
回到蓝图内,创建DT_PrimaryAttibutes,结构类型是GameplayTagTableRow
在UI内创建DT_MessageWidgetData,结构类型是在OverlayAuraWidgetController.h内创建的结构体UIWidgetRow
在WidgetController内修改
在Project Setting内的Gameplay Tag内修改