AbilityTasks not Destroyed when parent Ability ends if during Task Activation

When a GameplayAbility is ended during a child AbilityTasks activation, the child AbilityTask is not destroyed and will continue to Tick (if enabled)

See Repro steps for more details but as mentioned, the Repro is a very direct case for this happening with the Task calling Cancel on it’s parent ability. In reality this was found via a series of callbacks (Task set a movement mode, which triggered a callback, which editing the character dimension, …, which ended the ability)

If approved I can make a Github pull request but thought it was worth discussing here first.

Steps to Reproduce
Setup:

  • Base is the Third Person Starter Project
  • Add AbilitySystemComponent to Character BP
  • Add the EPS_GameplayTaskEndingAbility plugin provided in the attached Repro Zip to your project
    • Just a basic ability that has a single task that ends it’s parent ability in it’s activation, with logging.
  • Add to Level BP logic to trigger provided GameplayAbility_AbilityToEnd in Repro Zip on Debug Key 1 Press
    • Or trigger it another way, this is just what I found easiest for testing.

Repro:

  • Load into level
  • Press 1
  • Observe Output Log
    • May need to boost verbosity of LogTemp channel where I’ve added logging

Observation (Surface):

  • When the ability ends the child task continues to Tick

Observation (Code):

  • When the ability ends [UGameplayAbility::EndAbility] on line 852 it cycles through it’s ActiveTasks and tells them to end.
  • However in the tasks activation process [UGameplayTask::PerformActivation] it has yet to call the OnGameplayTaskActivated flow [UGameplayTasksComponent::OnGameplayTaskActivated -> UGameplayAbility::OnGameplayTaskActivated] so it hasn’t been added to the ActiveTasks list yet

Proposed Solution:

  • Adding a list of OwnedTasks alongside ActiveTasks that’s added to in [UGameplayAbility::OnGameplayTaskInitialized] that is iterated through in [UGameplayAbility::EndAbility] instead of ActiveTasks.
    • See GameplayAbility.h/cpp files in the attached Repro Project,

Failed Attempted Solution:

  • I initially tried adding a check for bIsActive in [UGameplayAbility::OnGameplayTaskActivated] before adding to ActiveTasks, calling TaskOwnerEnded on the Task if not. However if the InstancingPolicy is InstancedPerExecution then in [UAbilitySystemComponent::NotifyAbilityEnded] it marks the ability as garbage (line 1252) so in [UGameplayTasksComponent::OnGameplayTaskActivated] TaskOwner is null so [UGameplayAbility::OnGameplayTaskActivated] is never called.

Notes:

  • The proposed solution works for all InstancingPolicies
  • Debugging tools would need extending [I.e. Debug logs of ActiveTasks would likely want to include a section/version for OwnedTasks too]

Hi [mention removed]​,

Thanks for the detailed steps. Unfortunately, I haven’t been able to integrate the plugin you shared into an empty Unreal Engine 5.7 project.

Could you please review the plugin on your side so we can continue working on the issue and try to find a solution together? I’ll also check whether this issue has already been addressed by Epic, and if not, we can look for a workaround in the meantime. If I’m able to reproduce the bug consistently, I’ll report it to Epic so they can work on an official fix. Since this relates to GAS, it’s possible they’re already aware of it or actively working on it.

Best regards,

Joan

Hi Joan,

That’s strange, I’ve tried again via the Package Plugin interface so hopefully this one works!

I have a hacky workaround for the case I found (Breaking the chain that caused the task to end the parent ability)

If the plugin doesn’t work again for some reason, all it is is a basic ability and task, the ability creates the task, the task ends it’s parent ability in it’s activate. So easy to replicate locally.

I’ll be looking at using the fix I proposed for our project too but naturally would be nice for it to be an official change rather than an engine modification :slight_smile:

Cheers,

J

EPS_GameplayTaskEndingAbility.zip(26.8 MB)

Hi [mention removed]​,

I’m now able to open a new project with the plugin :slightly_smiling_face:

That said, I wasn’t able to open the .uproject you sent me. It’s possible the engine version used to create the project is a custom build, and even though it’s based on 5.7, some differences might have been preventing it from opening correctly on my end.

I didn’t dig too deeply into this, as I was able to get it working by integrating the plugin into a blank Unreal 5.7 project manually. After doing that, everything built and ran as expected.

The only issue I found is that the plugin was missing the dependency to the GameplayAbilities plugin, which was preventing the build from completing. I just wanted to mention it in case it helps with other GAS cases.

I’ll look into the original issue and will update you as soon as possible.

Thanks again!

Best regards,

Joan

Hi [mention removed]​,

I’ve tested the issue and was able to reproduce it. I also tested it on the Unreal dev branch, and it looks like the issue has not been addressed there yet. I’ve reported this bug to Epic so the Unreal devs can review it.

I included your workaround in the report, which I personally think is correct. I also mentioned the possibility of submitting it as a pull request, as that’s sometimes their preferred approach, but we’ll need to wait for their response. They’ve been notified, and once I hear back from them, I’ll let you know. Depending on the outcome, an Epic dev may also respond directly in this thread.

I’ve also opened a public bug tracker entry. Once it’s available, I’ll reply again in this thread. It will be published at: https://issues.unrealengine.com/

Best regards,

Joan

Hey Joan,

Apologies for the mess with getting the plugin setup, not sure why it’s been so messy since I’m using the latest release pulled directly from the github repo!

Good to know for future reference and thanks for relaying this to the team :slight_smile:

Cheers,

J

No issue Jordan! I’ll update the thread once I get some news.

Best,

Joan

Hi [mention removed]​,

I’ve recieved the public bug tracker link. Once Epic makes it public, you will see the full report in: https://issues.unrealengine.com/UE-363224.

Once fixed, they normally add in which future unreal engine version it will be published, and also the fix CL/Commit so you can integrate it directly to your current engine.

Cheers,

Joan

That’s grand!

When is that likely to be public?

And does this mean Epic want to investigate a different fix? I.e. I shouldn’t make a github pull request for this change?

Cheers,

J

Hi Jordan,

This will ultimately depend on Epic. Once they start addressing the case, they’ll review both the report and this thread and they will also generate the public link tracker post. I’ve already attached the solution you mentioned to the report, along with the files you proposed.

If you’d like, you can also submit a pull request, and I can attach that to the report as well. That said, the solution files have already been shared with Epic, so they have the necessary information.

I can’t provide a specific timeline for when this might become public, but Epic typically prioritizes bugs based on impact and importance. I do believe this issue is worth addressing, so hopefully it will receive higher priority than some other cases.

Let me know if you’d like to move forward with a pull request. As mentioned, your proposed solution has already been sent to Epic :slightly_smiling_face:

Best regards,

Joan