In a previous article we saw a very premature version of the physics prediction system that now bundles with Unreal Engine. Now, in Unreal Engine 5.4 the system has matured a lot and in todays article we will do a hands-on together.
Introduction
Predicting and correcting physics is one of the most complicated topics when it comes to network prediction. The nature of the complexity comes by the fact that if we hit a chain of physics objects on the client, we’d expect all the physics to react instantaneously, without having to wait for the server. But not only that, these physics objects should smoothly correct their position on the clients if there are incongruences with what the server expects. So you can imagine how difficult this can get with complex physics chain reactions.
Fortunately, Epic has been working lately in a solution for all these problems bundled in their Networked Physics solution. Before digging onto the matter, I strongly recommend everyone to take a look to this article, where Epic digs further on the different physics replication modes they brought to the engine with this new system.
Making a rolling boulder
I decided to make this post as I couldnt find any simple example around the engine on how to use properly the new Networked Physics system. The ‘rolling boulder’ we are going to create may serve as a “hello world” for those that would like to get introduced in the matter, as this new system can be used to make any type of vehicle or physics controllable object. Because… what’s easier than a rolling sphere?
However, this tutorial comes with a big disclaimer, as we are in a very early r&d phase, and we dont have yet any official technical documentation on the matter, other than the engine itself, and… my own assumptions!
So… as I always say, don’t trust random articles from the internet and please, do your own research! If you think that any of the information shared in here is off, you can always contact me on twitter and we can fix it together as a community effort! Now… lets get into it :D!
The setup
In order to activate the feature, open Project Settings and within the Physics tab, turn on Enable Physics Prediction.
There are other settings you might want to explore!
Then, lets not forget to enable the following settings in the same tab:
One of the core components of the new physics system is the UNetworkPhysicsComponent, and to date, this component enforces us to wrap our movement code in another component, so we’ll have a physics movement component and a controllable pawn that holds said component, let’s create the pawn:
Pay close attention to the replication settings, as they will play a relevant role in our implementation. Worth noting that the physics replication mode we are choosing for our boulder is Resimulation; in addition im leveraging a really low Net Update Frequency (not using Iris yet!), simply to show how great this system is.
And to finish up the setup, let me share with you my root static mesh settings that we use for the physics simulation:
Main important points from the image above is that, we need to turn on physics simulation, set the collision channel to something sensitive, and finally, ensure that the Component Replicates flag is off, we don’t need it, we are replicating the transform of our boulder by other means.
Coding the physics boulder movement
The way I’ve found other systems in the engine forward their physics input to the server is by means of the UNetworkPhysicsComponent. This component not only takes care of that, it also mantains historical records of both inputs and states, enabling the rewind and resimulation of physics simulations, crucial for maintaining consistency and accuracy in multiplayer environments. So, let’s make use of these features!
The UNetworkPhysicsComponent requires us to create two structs, which hold the input and the state of our physics simulation:
Note that, in my case I don’t require to keep track of any state of my boulder, but I still need to create the struct since the system requires it so.
Following next, the declaration of my movement class, I decided to use a UPawnMovementComponent in this case:
And finally, the implementation:
Note that the implementation above is just a “hello world”, it doesnt do any input sanitization in the server for simplicity.
If you did everything correctly, now you should have something as follows:
The above video was recorded with average latency everywhere (server and client). At the end of the video I display the difference between jump inputs being sent through the NetworkPhysicsComponent, and Jumps performed only on the client; you can see how the later get corrected, making the local sphere snap back to the ground.
Note: The Physics Resimulation replication mode currently has some bugs in PIE, where if you try to add more than one client, it starts behaving erratically.
Implementation details
Now that we all are in the same page, I think its worth noting different details from the implementation from above.
At the start of our physics simulation (OnCreatePhysicsState), we let the NetworkPhysicsComponent know which data it should handle for our physics simulations. It’s like magic – super simple to use! We just need to specify the data’s type, the component holding it, and then implement overrides for input and state handling. ApplyData and BuildData are key here; they smoothly transfer data between our movement component and the NetworkPhysicsComponent, which takes care of all the nitty-gritty details of state and input management for us.
The input processing goes like this: during AsyncPhysicsTickComponent, inputs are first applied locally, then the server catches up. This allows for predictive autonomous proxy simulation followed by server validation
Now, we’re mostly dealing with continuous input streams, like movement directions or camera orientation (TravelDirection), which are straightforward. However, sending one-frame events, like a jump action, is still a puzzle. I’ve experimented with boolean input variables, such as bJump, but encountered issues – the server sometimes missed the update because the variable reset before the NetworkPhysicsComponent could transmit it. This led me to try alternative approaches, like using JumpCount to increment with each jump action. However, I’m not entirely certain if this method aligns with Epic’s recommended practices.
Another thing worth to note is that, if you look at the other physics examples around in the engine, they explicitly process the input in OnPhysScenePreTick, part of the Physics Scene. I’m however not sure of the extra-implications of this and I would love to know; but at least, in this minimal example we got something working in less than 400 lines of code.
Additional resources
Besides this post, you can also take a look at different systems from the engine that also make use of this technology:
Finally, I strongly recommend everyone to take a look at Epic’s GDC talk about Chaos, where they talk a bit about their new physics system:
Thanks Epic!
Conclusion
Today we explored together the UNetworkPhysicsComponent and coded together a “hello world” physics boulder.
Note that this toy example uses a very simple setup for preview purposes. But I’d like to support it following the best practices, for that reason I’ll be mantaining it in my experimental arcade vehicle sample repo. Feel free to open issues or pull request to the sample, I’ll be vigilante, the main intention is to create a “hello world” example the community could learn from. And of course, along with that I’ll try to keep this article updated!
As always, feel free to contact me (and follow me! hehe) if you find any issues with the article or have any questions about the whole topic.
In this post we’ll learn a very cool trick to enhance your multiplayer logs. It consists on accessing the server instance from the client in the editor. But ...