Replicating Play Montage Behaviour

I’m attempting to learn GAS and Unreal at the moment, and I’m having some trouble understanding some discrepancies with my replication behaviour for the PlayMontage node. Essentially, the below image is the implementation for a “hitreaction” ability being called on an actor upon receiving damage.

This works just fine on server, and on client when the client actor receives damage. However, on client, the server actor doesn’t react when receiving damage, pointing me towards an oversight in replication.
However, a different ability that also uses the Play Montage node, being activated through the exact same method, has no problem replicating its montage.
The full implementation of the other ability is shown below, for reference, with the relevant node highlighted, as I’ve been informed “PlayMontageAndWait” has its own replication logic.(2 parts)

Both abilities have their replication settings the same, as shown below.

Could someone inform me on why the behaviour is different between the two abilities?

the montage is not the thing being replicated, the ability activation is. play montageAndWait only runs where the ability runs, so if the hit reaction ability activates on the client only, the server never plays it. your working ability almost certainly gets activated on the server while the broken one is being triggered from a client path.

how to confirm: print has authority and the ability activation in try activate abilities on the server side. trace the damage event: when damage is applied, who calls try activate on the hit reaction ability? if the damage is applied on the server but the ability is activated through an input or event that runs locally, you get exactly your symptom, client reacts to its own damage, server ignores everyone else.

the standard shape for a hit reaction:

  1. damage is applied on the server (make sure your apply gameplay effect to target runs with authority).
    1. the target sends a gameplay event to itself (target got gameplay event, hit reaction tag) inside the execution, or the damage handler calls try activate abilities by tag on the server.
    1. the ability activates on the server, play montageAndWait runs there, and gas replicates the montage to the owning client automatically. for other clients and simulated proxies, either drive a montage node in the anim bp from replicated state, or use a montageset with the ability task replication if you are on a version that supports networked montages.
      also check the two abilities side by side for: instancing policy (non instanced abilities have different replication behavior), net execution policy (server initiated vs local predicted), and whether one of them is being activated by an event the server receives while the other is triggered by input on the client. the discrepancy between the two abilities is the clue, same task, different activation path.

Testing right now but the source of confusion is that in the process of testing I activated both abilities from the same node to see if this was the issue and the discrepancy was still present at the time, so everything before ActivateAbility should be the same (logic pictured below, first function skipped just in case for testing, loadout ability was the only thing swapped between testing), meaning the issue isn’t related to the activation source (from my understanding). When Play Montage is replaced by Play Montage And Wait, it replicates just fine, enforcing that belief.

Testing format for hitreact:

Continuing on this train of thought, I did 2 things in the AOE ability to test behaviour.

First, I attached nothing but a play montage node to that ability start event. This montage played serverside, and didn’t replicate. Next, I skipped over the play montage node between Remove GameplayCue From Owner and the Delay node, just to ensure it was replicating. Sure enough, it was. Upon reconnection, the montage still replicates from that node, with nothing else changed. This tells me that somewhere in the GA_AOE Ability node logic, i’m causing the montage to somehow replicate. What is exactly causing that? Because this is all happening in the same GA blueprint, we know there’s no implicit variation in the class settings for replication, or variation in the calling source, yet playmontage is being replicated in one case but not the other. This perplexes me quite a bit.

PlayMontageAndWait is the GA task that talks to your ASC and replicates the montages within GAs to clients. The normal PlayMontage does not do any networking/sync. Only your GA start and end will replicate to clients under a Do Not Replicate policy.

For hit reactions, use a GameplayCue. That’s what they’re designed for. Use MakeGameplayCueParametersFromHitResult.

You can use PlayMontage in a GameplayCue, no problem.

I might be misunderstanding something here, but does that not mean the expected behaviour is that the Play Montage node in my AOE ability shouldn’t replicate? However, that animation replicates just fine, despite not being Play Montage and Wait. I’m confused at the discrepancy between the behaviours here.

Are you sure it’s replicating? The only place the GA logic should be executing is on the predicting client and the server (assuming you’re using mixed or minimal mode for your ASC). The other clients will receive updates to the attributes and tags (including gameplaycue tags) and multicasted GCs (gameplaycues you call manually rather than thru the GE). playmontageandwait sends an animationID i believe. The networked data in GAS is very stripped down for the clients.

countsie is pointing at the right thing, and your tests are actually consistent with each other once you account for where the ability graph runs. your controlled swap test also rules out the activation path theory i gave earlier, so credit for that isolation.

plain playmontage is not replicated, full stop. what makes it confusing is that the ability graph itself executes on more than one machine. a locally predicted ability activates on the server and on the owning client, so a bare playmontage node inside it runs locally on both. in a two window pie test that covers every window you have: the server window is the host (autonomous on the server), the client window is the owner (autonomous on the client). both play the montage on their own machines, nothing crosses the network, and it looks exactly like replication. the only spectator that could expose the difference, a simulated proxy watching the caster, does not exist in a two window setup.

so the flip flop between your runs is observation, not the node: what you verified when you bypassed playmontage (the cue and state changes) is genuine replication, and what you saw when you reconnected it was the second local execution, not the network.

two things settle it:

run three clients (or two clients plus the server) and in each window watch the other player’s pawn, not your own. plain playmontage: the caster plays it, everyone else’s view of the caster idles through it. playmontageAndWait: every window sees the caster play it, because that task routes through the ability system component, which replicates the montage params so simulated proxies play it too. that is the entire discrepancy between the two nodes.

also check the asc replication mode on your player state/character (default is mixed). if it somehow got set to full, the ability graph spawns on every client and even a bare playmontage plays everywhere, which would replicate for the wrong reason. mixed or minimal is what you want, and under those modes countsie’s description is exact: only server and predicting client run the graph, everyone else gets attributes, tags and multicast cues.

for hit reactions specifically i’d second the cue pattern: a gameplay cue with playmontage inside, fired from damage application with MakeGameplayCueParametersFromHitResult so the cue carries the hit info. cues multicast to all clients including simulated proxies, they work on npcs with no ability running at all, and they keep cosmetics decoupled so any damage source can trigger the reaction without activating an ability. reserve playmontageAndWait for montages that are genuinely part of the ability state, where the completed and interrupted callbacks gate the rest of the graph.

Ah, my issue was testing with only 2 clients instead of 3 it seems - testing on 3 indeed has the play montage portion not replicate onto the 3rd client as you posited. I’ll be replacing all instances where i’d want just a “play montage” with a cue application for proper replication then, and hopefully all will be well o7