Best Practice for creating a replicated "Push and Pull system" (similar to the mechanics from games like Moving Out)?

Hello,

I want to create a multiplayer-ready “Push and Pull system” , similar to the mechanics from games like “Moving Out” or “The Stretchers”. The player should be able to grab a physical object and push or pull it. Other players should be able to grab that physical object as well and drag each other.

My first idea was to make an ANetworkedPhysicsActor (with UNetworkPhysicsComponent and a MeshComponent that simulates physics), and add the UPhysicsConstraintComponent to my Player Pawn, then call the UPhysicsConstraintComponent::SetConstrainedComponents function both on the server and the autonomous proxy to drag the ANetworkedPhysicsActor. It works okay if only 1 player carries the ANetworkedPhysicsActor, but breaks if another player starts carrying the same Actor. The first player is not automatically dragged when the second player pulls the ANetworkedPhysicsActor and the other players attached.

Since there are no replicated variables in the UPhysicsConstraintComponent, maybe my whole approach is wrong and such a system should be done in a completely different way.

Can you help me and tell me any tips on how to properly implement such a system in a multiplayer game?

[Attachment Removed]

Hello Urszula, I’ll try to help you out by giving you a few directions but we don’t have a plug-and-play system that handles this at the moment.

First off, the networked physics model that our physics-based pawn solution (Chaos Mover) is using is designed for 100% server authority. Server authority adds a lot of complexity though, and it’s most often quite redundant for physics-based party / coop games like “Moving Out” since you don’t really expect cheating or care about cheaters in those games so they can get away with full client authority or partial client authority. Unreal Engine does not have a system for a physics-based client authority pawn though.

There are four different approaches you can take (probably more) but most of them require you to code and solve some problems.

1. Chaos Mover with Predictive Interpolation (easiest)

Enable these settings:

  • Physics Prediction in Project Settings → Physics → Replication.
  • Tick Physics Async in Project Settings → Physics → Framerate

Make your pawn physics-based with Chaos Mover, set it to Physics Replication Mode: Predictive Interpolation (not Resimulation).

Note that Predictive Interpolation will result in input latency on your pawn linked to your network latency. This can be okay depending on your game, this is how physics vehicles in LEGO Fortnite works for example but for other games it might be unacceptable.

Now you have a physics-based pawn so the UPhysicsConstraintComponent can affect it.

You need to replicate the attachment of the UPhysicsConstraintComponent yourself though by writing your own component on the objects that you can grab which replicate to clients who are attached to them. Your pawn needs to replicate an RPC to the server saying it wants to grab the object and then the server via your new component needs to create the constraints between the pawn and the object and then replicate from the server to clients which pawns are connected to the object so clients can create the constraint also, on all clients.

Pawns and objects are all physics simulated and they will affect each other, there will be some latency in the system since Chaos Mover is server authoritative and you won’t have any good client-side prediction with this system.

2. CharacterMovementComponent (CMC) pawn with custom pull/push forces

The CMC pawn does not handle being physics-based, it’s a kinematic (infinite mass) pawn. That means that UPhysicsConstraintComponent can’t affect the pawn, so there can’t be two-way interactions based on the constraint, you can hook up the constraint to the pawn and a dynamic object and the constraint will affect the dynamic object but not the pawn.

The CMC has partial client-authority though and it has API to act on forces / impulses as if it was physics-based.

This means that you can write your own pull/push logic that calls UCharacterMovementComponent::AddForce to move the pawn and call UPrimitiveComponent::AddForce on the root component of the object you are holding to move that.

I’m not well versed in CMC though and there might be things that pop up that I can’t forsee that you might solve but in theory this approach should work.

Also a note on CMC there is a solution for pushing but not a 2-way interaction, but worth looking at: “bEnablePhysicsInteraction”.

Same here that you need your own logic on the object that knows which pawns are “attached” and that replicates that data to server and from server to other clients.

I’d also recommend using Predictive Interpolation on the dynamic physics objects that you move and enable these settings if you do:

  • Physics Prediction in Project Settings → Physics → Replication.
  • Tick Physics Async in Project Settings → Physics → Framerate

3. Resimulation with Chaos Mover

Go with the 100% server-authoritative networked physics solution we have with Physics Replication Mode: Resimulation.

Enable these settings

  • Physics Prediction in Project Settings → Physics → Replication.
  • Tick Physics Async in Project Settings → Physics → Framerate

This is a complex workflow though and I’ve not tried UPhysicsConstraintComponent with resimulation, it probably works for the most part but some aspects like creating and destroying it might have some desync issues since resimulation probably doesn’t handle those events.

Again you need to replicate yourself which pawns and objects are attached and make sure the UPhysicsConstraintComponent are created on clients and server correctly.

Alternatively the best approach here would be to write your own constraint on the physics thread via ISimCallbackObject and then use the NetworkPhysicsComponent’s Action system to connect the constraints between pawns and objects. Since it’s purely physics-thread based and using NetworkPhysicsComponent then it will handle physics resimulations perfectly.

I can’t go into more detail here about this though, I’ll post two tutorials at the end about networked physics and resimulation if you want to dig in and do this approach but it’s as mentioned before a bit complex, not plug and play and a bit overkill for your usecase I think.

4. Make your own client-authority solution for physics-based pawns

This might be complex but might also work with some simple implementation, I don’t know.

This is something I want to provide as an Unreal Engine feature at some point but it’s not currently on the schedule so don’t rely on this coming officially anytime soon.

You need to make your own actor or pawn-class which override incoming AActor::ReplicatedMovement via AActor::OnRep_ReplicatedMovement() / AActor::PostNetReceivePhysicState() so it doesn’t act on them via physics replication client-side for the autonomous proxy. It also needs to send your physics-state to the server and apply that on the server, stomping whatever the server has.

You can look at how the server grabs the physics state currently via AActor::GatherCurrentMovement which gets the physics state from FPhysScene_Chaos.GetStateFromReplicationCache.

I’d recommend having these enabled:

  • Physics Prediction in Project Settings → Physics → Replication.
  • Tick Physics Async in Project Settings → Physics → Framerate

And use Predictive Interpolation as the replication mode for physics objects and simulated proxy pawns.

With this approach you should be able to use UPhysicsConstraintComponent if your pawn is physics-based (Chaos Mover or a custom made pawn) and you still need to make sure all clients and the server apply the same UPhysicsConstraintComponent between objects and pawns.

Tutorials:

Networked Physics: Fundamentals: https://dev.epicgames.com/community/learning/tutorials/5E4w/unreal-engine-networked-physics-fundamentals

Networked Physics: Pawn Tutorial: https://dev.epicgames.com/community/learning/tutorials/MoBq/unreal-engine-networked-physics-pawn-tutorial

I’m coming out with another gameplay tutorial in a while also in this series.

Hope this helps at least!

Markus Boberg

Senior Network Physics Programmer

[Attachment Removed]

I don’t know enough about CharacterMoverComponent (CMC) to say for sure, but yes, any API on it that allows you to move it from external logic should work if you make your own logic that pushes / pulls the character / object.

[Attachment Removed]

Hello [Content removed]

Thank you for your answer.

I’ve noticed that your solutions mention either ChaosMover or CMC. I wonder if it should also be possible to create such a system with a regular MoverComponent/CharacterMoverComponent. I think the solution no. 2 can be also created with a simple CharacterMoverComponent, by applying either FApplyVelocityEffect or FLayeredMove_Launch?

[Attachment Removed]

FYI, the new tutorial for Networked Physics Gameplay is out and I showcase a 2-way interaction via a tether, not exactly your push-pull but the same thing can be done with the same solution just with different settings.

The tutorial is for pure network physics with physics resimulation though, not the CMC.