UE 5.11
While I was learning Lyra, I found an interesting Ability - GA_AbilityWithWidget
.
It uses two events Event OnAbilityAdded
and Eevent OnAbilityRemoved
.
I’ve done my own experiment, granting the ability via the Ability Component hoping it would create a Widget
via UIExtension
when the ability is granted, and then remove the Widget
from the UI
when the ability is removed.
But now it has two problems.
First, when OnAbilityAdded
, I added an element to WidgetExtensionHandles
, but when OnAbilityRemoved
, the array is empty.
why is that? I’m confused.
Secondly, I found a strange thing, if I set Activation Policy == On Input Triggered
in the Class Defaults
of this GA_AbilityWithWidget
, my blueprint node (Event OnAbilityRemoved
) will not execute, although I see in the Debug that it does executes the C++ code OnRemoveAbility
.
void ULyraGameplayAbility::OnRemoveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec)
{
K2_OnAbilityRemoved(); // Execute
Super::OnRemoveAbility(ActorInfo, Spec).
}
When I change Activation Policy == On Spawn
, the blueprint node executes correctly.
How do I fix the above problem?
Lyra GA_AbilityWithWidget
:
I just rewrote the logic in C++ and it works great, no problem. This blueprint is really hard for me, what am I doing wrong?
The Blueprint’s Activation Policy
is also On Input Triggered
::OnGiveAbility(const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilitySpec& Spec)
{
Super::OnGiveAbility(ActorInfo, Spec);
UUIExtensionSubsystem* UIExtensionSubsystem = GetWorld()->GetSubsystem<UUIExtensionSubsystem>();
this->WidgetExtensionHandle = UIExtensionSubsystem->RegisterExtensionAsWidgetForContext(
this->WidgetExtensionPointTag,
GetOwningActorFromActorInfo(), this->WidgetClass, -1);
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("OnGiveAbility"));
}
}
::OnRemoveAbility(const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilitySpec& Spec)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("OnRemoveAbility"));
}
UUIExtensionSubsystem* UIExtensionSubsystem = GetWorld()->GetSubsystem<UUIExtensionSubsystem>();
this->WidgetExtensionHandle.Unregister();
Super::OnRemoveAbility(ActorInfo, Spec);
}
Check the AbilitySystemComponent::OnRemoveAbility, It only trigger the OnRemoveAbility on primaryinstance if there is one.
// Notify the ability that it has been removed. It follows the same pattern as OnGiveAbility() and is only called on the primary instance of the ability or the CDO.
UGameplayAbility* PrimaryInstance = Spec.GetPrimaryInstance();
if (PrimaryInstance)
{
PrimaryInstance->OnRemoveAbility(AbilityActorInfo.Get(), Spec);
}
else
{
Spec.Ability->OnRemoveAbility(AbilityActorInfo.Get(), Spec);
}
2 Likes