Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RootMovement2D

A small Unreal Engine 5.8 plugin for dashes, knockbacks and shoves in top-down and side-scroller games, with replication that already works because the engine does it.

The problem it solves

You want a dash. Gameplay code decides the direction, so it can't come from an animation montage. Write the velocity math yourself and it feels fine in single player, then you spend a week on prediction and server reconciliation.

Unreal already has the answer in FRootMotionSource. Gameplay authors a force, the character movement component integrates it, and prediction, replay and server correction come along for free on the stock movement path.

RootMovement2D is a thin wrapper around that. One Blueprint node, two C++ statics, a demo character. The one thing it adds is bForce2D, which flattens the push onto the XY plane and scales it back up, so a character standing on a ramp still dashes along the ground and Strength means the same number whether you flatten or not.

That's the whole plugin. If you were about to write your own dash, use this instead and go build the game.

Using it

Drop the folder in YourProject/Plugins/, enable it, restart the editor.

In Blueprint the node is Apply Root Motion Constant Force with Callbacks. Give it a world-space direction, a strength, a duration, tick bForce2D, and bind OnComplete or OnFail. From C++ call URootMovement2DLibrary::Apply2DRootMotionConstantForce and hold onto the returned ID so you can Remove2DRootMotionSource later.

A2DRootMovementDemoCharacter is a working example of both. Subclass it in Blueprint, wire a key to DemoDashForward, and you have a dash. It deliberately ships no input bindings, because your project's input is yours.

A few things worth knowing about the parameters:

  • Duration follows the engine's rule, not a made-up one. Positive times out. Negative is infinite and runs until you remove it. Zero finishes on the first movement tick.
  • bEnableGravity sets the engine's IgnoreZAccumulate flag, so the push never fights gravity over the Z axis. Leave it on for anything that walks.
  • StrengthOverTime takes a UCurveFloat. A curve from 1 to 0 turns the constant force into a decaying one without any extra code.
  • A direction with no horizontal component is rejected when bForce2D is on. You get a warning on LogRootMovement2D and OnFail instead of a silent no-op.

Building it standalone against a source engine:

Engine\Build\BatchFiles\RunUAT.bat BuildPlugin -Plugin=<path>\RootMovement2D.uplugin -Package=<output> -TargetPlatforms=Win64

Networking, and one trap

There is no netcode in this plugin. Not a line. Prediction, replay and server correction all belong to the engine, and they work because nothing here goes around the stock FRootMotionSource path.

What you actually see depends on which machine applies the source:

  • Both machines. The client predicts its own copy the same tick, the server simulates the authoritative one, and the engine reconciles them when they drift. This is what a shipped player dash does, and it's what the GAS ability tasks do too. Use this one.
  • Server only. The client never predicts a source it didn't apply, so the motion arrives as corrections. Expect rubber-band. That's the role, not a defect.
  • Owning client only. This is the trap. The dash never reaches the server as data, because the packed client move carries no root-motion-source group. The server simulates your pawn without the dash, decides you're in the wrong place, and corrects you back. Fine for prototyping on a listen server where the host pawn is the authority. Do not ship it on a dedicated server.

If you go looking for the client-only trap in the logs, ClientAdjustRootMotionSource lines are the wrong thing to grep for. That channel carries the server's sources, so its silence tells you nothing. Watch LogNetPlayerMovement for ordinary position corrections instead, and turn the verbosity up first:

Log LogRootMotion Verbose
Log LogNetPlayerMovement VeryVerbose

The plugin's own channel is LogRootMovement2D and it prints at default verbosity.

Coming from the old RootMovement plugin

The archived plugin's node maps straight onto this one. Same eleven parameters in the same order, with bForce2D appended at the end, so a migration is mostly a node swap.

Under the hood a few things are different. The movement component is held weakly, so a character dying mid-dash no longer dangles a pointer. Cancel() removes only a source the node actually applied, instead of calling remove with ID 0. The strength curve is a tracked UPROPERTY, so garbage collection can't take it out from under you. A source the engine rejects fires OnFail rather than pretending to succeed. And the completion timer follows the engine's own timeout rule instead of guessing at it.

Where this might go

  • A Mover LayeredMove adapter, so the push composes with other layered moves.
  • A UCharacterTrajectoryComponent subclass feeding the active source into predicted trajectory samples for AI and ability targeting.
  • A GAS ability task wrapper, so abilities can drive dashes without raw timers.
  • Worker-thread-safe AnimInstance getters for live root-motion state.

No promises on any of it.

License

BSD 3-Clause. See LICENSE.

About

Replicated 2D root motion for Unreal Engine 5.8, built on the engine's Root Motion Source system.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages