-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UE5CoroGAS: "Overlapping ability activations with the same prediction" key when triggering ability from client #30
Comments
Thank you for the bug report, and I'm glad you find the plugin useful. I have an idea of what the problem could be (everyone loves multiplayer single-process PIE...), but I'm having trouble reproducing this locally. I filled in some of the blanks: made an ability that's activated by a tag, added the missing CommitAbility call so that it doesn't fail to activate, etc., but I'm not hitting the Could you please provide additional information? Some things that I'd like to know:
Please note that implementing ExecuteAbility with a subroutine is undefined behavior. |
Hey thanks for your quick reply. In my case the
Unreal Version: 5.4.2-33871570+++UE5+Release-5.4
Platform: Windows 10 (22H2) [10.0.19045.4651] (x86_64)
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
Im sending the Gameplay Event in response to a user's input action. Each Character has a InteractionsPlayerManager.cpp: void UInteractionsPlayerManager::HandleInputSelectInteraction(const FInputActionValue& InputActionValue)
{
if (UInteractableContextMenuWidget* Widget = GetInteractionsMenuWidget())
{
if(UCharacterAction* Action = Widget->GetHoveredAction())
{
CharacterManager->PerformAction(Action, DukesCharacter);
DukesCharacter->WidgetsController->RemoveHUDWidget(InteractionsMenuWidgetClass);
}
}
} InteractionsCharacterManager.cpp: UE5Coro::TCoroutine<bool> UInteractionsCharacterManager::PerformAction(UCharacterAction* Action, ADukesCharacter* SourceCharacter)
{
if(!Action)
{
UE_LOG(LogTemp, Error, TEXT("CharacterActionManager::PerformAction: Action is null!"));
co_return false;
}
if(!SourceCharacter)
{
UE_LOG(LogTemp, Error, TEXT("CharacterActionManager::PerformAction: SourceCharacter is null!"));
co_return false;
}
if(!Action->IsActionExecutionPossible(SourceCharacter))
{
UE_LOG(LogTemp, Error, TEXT("CharacterActionManager::PerformAction: Character %s tried to execute Action %s, but execution is not possible!"),
*UKismetSystemLibrary::GetDisplayName(SourceCharacter),
*UKismetSystemLibrary::GetDisplayName(Action));
co_return false;
}
DUKES_LOG(LogTemp, Display, TEXT("CharacterActionManager::Sending Gameplay Event %s to character %s"), *Action->ActionEventTag.ToString(), *SourceCharacter->GetName());
FGameplayEventData EventData;
EventData.Instigator = SourceCharacter;
EventData.Target = Action->GetOwner();
EventData.OptionalObject = Action;
ActionBeingPerformed = Action;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(SourceCharacter, Action->ActionEventTag, EventData);
co_await OnPerformFinished;
co_return true;
} The GameplayAbility itself marks itself as triggered through GameplayTag by calling this in its constructor: void UDukesGameplayAbility::InitWithTagTrigger(FGameplayTag TriggerTag)
{
this->ActionEventTag = TriggerTag;
FAbilityTriggerData AbilityTriggerData;
AbilityTriggerData.TriggerTag = TriggerTag;
AbilityTriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent;
AbilityTriggers = {AbilityTriggerData};
}
The Actor receiving the event is a PlayerCharacter. The ASC is placed on the Actor itself. AbilitySystemComponent = CreateDefaultSubobject<UCharacterAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
Calling
When starting PIE as client the problem still occurs.
Could you elaborate on this a little more? A subroutine in C++ is just a normal function right? In my case im implementing |
Thank you for the additional information, I've managed to reproduce the issue.
Yes. You're almost certainly doing this correctly, but since you mentioned that "Removing the co_await from ExecuteAbility fixes this issue." I thought I'd highlight this as a potential pitfall when working with UE5CoroGAS. |
@JonathanIlk I have an attempted bugfix on the Could you please test how it behaves in your project? I've added some logging to UUE5CoroGameplayAbility. I'd like to know if there are any leaks in |
Hey, thanks for the quick reply and the even quicker bugfix. It seems like the issue with the duplicate PredictionKey is fixed now. However there is another issue where the Coroutine execution after a
My ExecuteAbility looks like this: UE5Coro::GAS::FAbilityCoroutine UCharacterActionAbility::ExecuteAbility(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
CommitAbility(Handle, ActorInfo, ActivationInfo);
DUKES_LOG(Interactions, Warning, TEXT("CharacterActionAbility about to wait 1 Second"));
co_await UE5Coro::Latent::Seconds(1);
DUKES_LOG(Interactions, Warning, TEXT("CharacterActionAbility just waited 1 Second"));
co_return;
} As you can see for the first and third attempt the second |
Could you please include I can produce similar "mismatched" ability activations using pure BP ( |
Logs with [0389.26][151]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Start [10/9]
[0389.26][151]Dukes_Interactions: Warning: Client-HarvestPlantActionAbility_0:CharacterActionAbility about to wait 1 Second
[0389.26][151]LogAbilitySystem: PlayerCharacter_C_1: Activated [29] HarvestPlantActionAbility_0. Level: 1. PredictionKey: [10/9].
[0389.46][156]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Start [10/0]
[0389.46][156]Dukes_Interactions: Warning: Server-HarvestPlantActionAbility_0:CharacterActionAbility about to wait 1 Second
[0389.46][156]LogAbilitySystem: PlayerCharacter_C_1: Activated [29] HarvestPlantActionAbility_0. Level: 1. PredictionKey: [10/0].
[0389.61][159]LogAbilitySystem: Verbose: PlayerCharacter_C_1: Server Confirmed [29] Default__HarvestPlantActionAbility. PredictionKey: [10/0]
[0389.66][160]LogAbilitySystem: Verbose: FReplicatedPredictionKeyItem::OnRep [10/0]
[0390.30][173]Dukes_Interactions: Warning: Client-HarvestPlantActionAbility_0:CharacterActionAbility just waited 1 Second
[0390.30][173]LogAbilitySystem: PlayerCharacter_C_1: Ended [29] HarvestPlantActionAbility_0. Level: 1. WasCancelled: 0.
[0390.30][173]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] End [10/9]
[0390.30][173]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Activations 2->1
[0390.42][176]Dukes_Interactions: Warning: Server-HarvestPlantActionAbility_0:CharacterActionAbility just waited 1 Second
[0390.42][176]LogAbilitySystem: PlayerCharacter_C_1: Ended [29] HarvestPlantActionAbility_0. Level: 1. WasCancelled: 0.
[0390.42][176]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] End [10/0]
[0390.42][176]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Activations 1->0
[0391.62][204]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Start [12/11]
[0391.62][204]Dukes_Interactions: Warning: Client-HarvestPlantActionAbility_0:CharacterActionAbility about to wait 1 Second
[0391.62][204]LogAbilitySystem: PlayerCharacter_C_1: Activated [29] HarvestPlantActionAbility_0. Level: 1. PredictionKey: [12/11].
[0391.83][208]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Start [12/0]
[0391.83][208]Dukes_Interactions: Warning: Server-HarvestPlantActionAbility_0:CharacterActionAbility about to wait 1 Second
[0391.83][208]LogAbilitySystem: PlayerCharacter_C_1: Activated [29] HarvestPlantActionAbility_0. Level: 1. PredictionKey: [12/0].
[0391.94][210]LogAbilitySystem: Verbose: PlayerCharacter_C_1: Server Confirmed [29] Default__HarvestPlantActionAbility. PredictionKey: [12/0]
[0391.94][210]LogAbilitySystem: Verbose: FReplicatedPredictionKeyItem::OnRep [12/0]
[0392.65][225]Dukes_Interactions: Warning: Client-HarvestPlantActionAbility_0:CharacterActionAbility just waited 1 Second
[0392.65][225]LogAbilitySystem: PlayerCharacter_C_1: Ended [29] HarvestPlantActionAbility_0. Level: 1. WasCancelled: 0.
[0392.65][225]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] End [12/11]
[0392.65][225]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Activations 2->1
[0392.81][229]LogAbilitySystem: PlayerCharacter_C_1: Ended [29] HarvestPlantActionAbility_0. Level: 1. WasCancelled: 0.
[0392.81][229]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] End [12/0]
[0392.81][229]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Activations 1->0
[0392.81][229]LogAbilitySystem: Verbose: IsEndAbilityValid returning false on Ability HarvestPlantActionAbility_0 due to EndAbility being called multiple times
[0392.81][229]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] End [12/0]
[0392.81][229]LogUE5CoroGAS: Warning: [UE5CoroGAS Temp] Activations 0->0 If this behavior also exists when using GAS without UE5Coro, I would consider this fixed. Can't expect this library to fix Engine bugs. Thanks for your quick help! |
Just to confirm, what happens in your project if you use a pure BP GA with the same replication/instancing/etc. policies? My message above describes the BP event graph that I was using for testing. UE5CoroGAS won't behave 100% identically to a pure GA, e.g., it guarantees that your coroutines' local variables will be destroyed properly, instead of just throwing away the BP mid-execution. |
Thank you for confirming.
Per-execution instancing seems to work better, although I haven't exhaustively tested if it avoided this specific issue. |
The fix has shipped in 1.10.3 and 2.0. |
The Problem
When executing a
UUE5CoroGameplayAbility
from the client theUUE5CoroGameplayAbility::CoroutineStarting
throws an exception "Overlapping ability activations with the same prediction key".This happens when the
ExecuteAbility
function contains aco_await
and the function resumes execution after waiting.Executing the same function from the server works as expected.
Implementation
This happens on UE5Coro 1.10.2 and UE5Coro 2 Preview 2. I upgraded my project to UE5Coro 2 to make sure the bug is still happening in the new version, so all examples from now on will be for UE5Coro 2.
Step 1:
Trigger the GameplayAbility by sending a GameplayEvent:
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(SourceCharacter, Action->ActionEventTag, EventData);
Step 2:
Implement the
ExecuteAbility
for theUUE5CoroGameplayAbility
in the following way:Step 3:
Start Play in Editor session with
Number of Players = 2
andNetmode = Play as Listen Server
Execute the
GameplayAbility
on the Client.Expected Result:
Ability is executed on client & server correctly.
Actual Result:
The ability execution breaks with error "Overlapping ability activations with the same prediction key" because of this line in
UUE5CoroGameplayAbility::CoroutineStarting
:Removing co_await
Removing the
co_await
fromExecuteAbility
fixes this issue. Which makes me think that the cause is somewhere in the logic where the Ability execution resumes after co_await. Maybe the Ability is then treated as fresh ability and sent to the server once again which then complains about duplicate Prediction keys.P.S.: Thanks for this plugin, I'm trying to write as much of my gameplay logic in C++ as it feels more maintainable to me having my logic in code. Without this plugin it was an absolute mess waiting for all those delegates, with this plugin the code is way cleaner.
The text was updated successfully, but these errors were encountered: