Timing issue with Gameplay Cues Under Mixed Replication

We ran into a timing issue with Gameplay Cues when predicting Gameplay Effects on a target Ability System Component (ASC) while using mixed replication.

Here is a breakdown of the flow and where we see the problem.

1. Ability Flow

Client Side prediction

  • The client starts an ability.
  • Predictively applies a Gameplay Effect with a duration to a target ASC.
  • The Gameplay Effect triggers a Gameplay Cue, spawning a Niagara VFX.
  • We cache the pointer to this effect in the Gameplay Cue for removal in OnCeaseRelevant.

Server execution

  • The server executes the same ability.
  • Applies the same Gameplay Effect.
  • This causes the Gameplay Cue to replicate to the client.

We have observed two possible outcomes now:

Case 1: When it works properly

  • OnCeaseRelevant runs first, cleaning up the predicted effect and the Niagara system.
  • OnBecomeRelevant (OnActive) runs afterwards, spawning a new Niagara System/Effect.
  • Everything works as intended because the old effect was cleared by the time we spawn the new one.

Case 2: Timing/order issue occurs

  • OnBecomeRelevant from the replicated cue arrives before the client’s OnCeaseRelevant is called.
  • A new Niagara Effect is spawned on top of the old one (which hasn’t been cleared yet).
  • When the first OnCeaseRelevant finally runs, it removes the new effect, leaving the old one persisting.
  • If we try to remove the effect preemptively on OnBecomeRelevant, we risk deleting the only valid effect when OnCeaseRelevant runs.

We have tried a couple of workarounds that seem to work, confirming the issue explained above:

Workaround 1: Removing the client-side predictive effect

  • Avoids overlapping cues entirely.
  • Works but reduces responsiveness from client prediction.

Workaround 2: Counting OnActive and OnRemove calls:

  • Only remove the effect when the counts match.
  • On OnActive, remove the effect if it already exists.
  • On OnCeaseRelevant, remove the effect only when the counts are the same.
  • Works reliably but is essentially an ugly hack to work around the race condition.

Is it possible to know if the calls to OnBecomeRelevant and OnCeaseRelevant are coming from replicating or prediction? Is there a better approach to do this? Can we somehow enforce the order? Should OnActive and OnRemove even be called when the server corrects the Gameplay Effect?

I have added a graph that hopefully illustrates the issue a bit better.

Thank you so much.

Steps to Reproduce

  • Run an ability predictively on the client.
  • In the ability apply a gameplay effect with duration on a target ASC while using mixed replication.
  • Add a gameplay cue on said gameplay effect.
  • Create and cache a niagara effect on your cue on become relevant.
  • Clear the effect on cease relevant.
  • The server will run the ability, apply the effect and trigger the cue as part of the replication process. Observe that the old niagara effect will remain orphaned when the gameplay cue functions are called out of order.

This is an issue that we’re trying to address as we move forward with the future of GAS. Due to the unreliable nature of the replication ordering there’s no guarantee that the predicted effect will be correctly cleaned up before the new one is applied. Your workarounds are exactly what I would suggest for this scenario.

Our first attempt to address some of this issue is in the gameplay tag application for Gameplay Effects, if these tests go well something similar may be rolled out across more parts of the system to allow better control of predicted objects.

Thank you so much for getting back to me Cody.

That is great, we can definitely live with our workaround for the time being. At least it is good to get confirmation that we were on the right track.

Good luck and I hope your tests go well!