Note: Predicting RootMotionSourceAbilityTasks works up to engine version 4.19 and 4.25+. Prediction is bugged for engine versions 4.20-4.24; however, the AbilityTasks still perform their function in multiplayer with minor net corrections and work perfectly in single player. It is possible to cherry pick the prediction fix from 4.25 into a custom 4.20-4.24 engine.
This describes behaiour I see in UE 5.3, which is:
How are you using it? And what exactly is not working?
When running RootMotionSource (ApplyRootMotionMovetoForce is a task that apply RMS to CharacterMovementComponent) on server, CMC will not replicate RMS directly, but will replicate the movement result to all clients on each tick. Hence, any way of applying RMS on server will work on server-side client as well as on remote clients
Nevertheless, by default on the client side RMS is still not “replicating” to server in any way, so if you call directly ApplyRootMotionMovetoForce on client - you will execute RMS only on client and will moved back to correct position by server, since this movement never happend on server.
This problem is usually solved by running RMS tasks inside of GameplayAbility with LocalPredicted or any other mode that involves ability call replication to server (iirc LocalPredicted is set by default). This way your GA’s code will be run both on client and a bit later - on server. And since the server was notified about RMS existance, it won’t rollback your position.
So, in first place make sure:
your ASC is properly setup;
that GA you trying to activate on the client does reach the server (mere print text is enough)
that you running ApplyRootMotionMovetoForce from inside of such GA
that you is not gating ApplyRootMotionMovetoForce execution on server by HasAuthority() or any other unintended way.
ps. Also, just tested this task on 5.3.1 and it works fine in both cases
ps2. GA-less RMS application is technically possible, but you should make work the default case first and then, i think there is no real reasons to do so.
Thank you for your answer, you were right.
Your answer helped me understand what should execute where (I’m one week new to both UE and GAS).
The cause for my issue was that I was calculating TargetLocation based on position on the mouse like so: ActorLocation + (VectorFromPlayerToMouse.Normalized * DashLength)
Since on server VectorFromPlayerToMouse would result in 0,0,0 - target location would be equal to current actor location, hence teleporting back.
I was thinking Ability would be executed on client and only effects of it would be replicated to server. But now I learned that the Ablity also executes on server. In this case I think I have to create replicated variable outside of Ability (in Player Character Blueprint?) with mouse location (or direction) that is updated by owning client only and replicated to server. That variable would be then used in Ability by both owner and server. Does it make sense?
Since you localized that the problem is in passing inputs to server, it makes following things easier. A few things about GAS’s intended way of handling this:
The easiest approach would be to use WaitTargetData task: on client it will send attached data to server and immediately continue execution; on the server it will wait for data from client and once received - it will continue execution from the same node in blueprint - quite a seamless way to pass client-side parameters to server.
Though, while it’s the easiest approach, it’s still may require some prior setup in cpp - look at examples and you should be able to make it work
This will mostly work, but it isn’t the perfrect solution: you using RPC to tell server about ActivateAbility() and then using another one (the WaitTargetData task) to tell it about the params you’ll be using. That’s fine if your ability involves active user targeting during some duration(ex. until mouse is clicked; if you handling this outside of GA, then i suggest to also read the TargetActors part, it may make some things easier for you). But if it’s just “Params are known at the start and should be passed to server immediately” - it will add an unnecessary extra delay in ability execution.
The proper approach for abilities with Instant targeting will be to pass TargetData along the first RPC that call ActivateAbility. The GAS does have some support for this feature in form of ActivateAbilityFromEvent event inside of GA, but to proper launch such ability call, especially if you want to activate it byClass… i don’t know how it’s now, but during 4.26 there was no built-in support for this in engine and my ASC have a bunch of custom logic to handle this that i still use in 5.3.1. Though tbh this custom logic is mostly slightly altered default functions with necessary params added