#16 Unreal Engine, Multiplayer, Rocket Controller, C++


From the last devlog: "Now I am looking into Multiplayer as well. It shouldn't be too hard with Lyra" - oh boy, was I wrong!

It has been 270 days since the last devlog and big part of why it took so long was due to taking care of multiplayer. Another reason was a big overhaul of the attitude controllers and implementing it in C++. These will be the main topics of this devlog.


Quick Recap

In March 2023 I got fed up with Unity when the SPMTs started glitching when being far away from the origin of the world (at the build site) and started to look into other game engines, first Unigine and then in May into Unreal Engine.

After publishing a small demo for supporters on Patreon in June, the time of the last devlog, I wanted to quickly add most of the Unity version features to the Unreal version, publish this here on Itch and then do a devlog again.

Well, that didn't go quite as planned and adding multiplayer to the Unreal version was a big part of the reason why everything took much longer.


Unreal Multiplayer

It's hard to estimate how much longer it took just to add features from Unity back to Unreal due to taking care of multiplayer support. At some point it felt like at least twice as long. However, currently, after spending a bit more time on unrelated stuff, I'd say it's not that bad overall, but still like 50% longer or so.

At least there is one good thing - it's fun! Multiplayer is fun! Even in the current, slightly scuffed form. It's especially fun for me, watching directly how people use the game and seeing them do dumb stuff like stacking ten booster on top of each other or using bugs to spawn and run around with dozens of Starships :D (that's still possible btw)


The thing with multiplayer is that Unreal Engine and the Lyra sample project, that I used as a basis, are perfectly suited for an arena style multiplayer shooter. Like Lyra has a nice way to support multiple game modes and such. But as soon as you add lots of physics to the mix, it becomes a nightmare. Even Unreal Engine, which probably has the best out of the box multiplayer support, at least out of the bigger engines, doesn't make it exactly easy to network physics. 

Of course, with physics there is the general problem that you have to transmit a lot of data to properly synchronize all the objects. There are different methods to reduce the bandwidth requirements while keeping it more or less jittery. However, AFAIK, Unreal Engine 5 currently hasn't any good method to replicate physics of a generic skeletal mesh, which I'm using for the rockets and transport stands. At least there is no out of the box client side prediction. I might be wrong though.

It's a little confusing right now with their new custom physics engine and poor documentation. On top of that, it's difficult to search for answers because they might be for the old physics engine. You have to wade through google results, the forum, youtube and the Unreal Source discord or ask for help there. If you are lucky, you meet a knowledgeable person that can help you. The other go-to solution for Unreal Engine issues is to look at the source code. But good luck trying to understand a physics engine when you are pressed to fix some annoying issues...

In the end I settled on using a standard skeletal mesh for the rockets with things like the engines as bones connected to the main body by physics constraints and updating this as often as possible. Since it doesn't have client side prediction, this method becomes problematic when going at high speeds or there is a lot of lag or the server has low FPS or  low bandwidth and lots of objects. But it's ok at least for the moment for moving things slowly around the base and maybe with future Unreal Engine updates it can be fixed or improved.

Constrained parts lagging at high velocity

Constrained parts lagging at high velocity


The Rocket Controller

The rocket controller does a bunch of calculations to separate the current attitude of the rocket into a component for each axis, feeds this into PID controllers which then give out values to the gimbal, grid fin or flap constraints to move them such that the rocket moves in the desired direction. 

This is a lot of calculations and they are done every tick. I set physics to a fixed 60 ticks per second using UE5's new async physics tick feature that allows to run the physics calcs in a separate thread. There are two problems here.

First, executing even basic functions in blueprints takes very long. If you do this every tick with a lot of calculations you get into trouble quickly. So you need to do this in C++.

Second, since the async physics are running in a separate thread from the main game thread with a separate tick rate, you need to make sure to access the correct thread when retrieving physics states or doing things like adding a force. Luckily, there is the ATP library for this that it makes super convenient. It's strange though that there are almost no built-in functions for that.

This is an example from the ATP library, not from the game

This is an example from the ATP library, not from the game

Unreal C++

I have worked with C++ before, but not that much and it was some time ago. Long enough to forget how pointers work and what you have to look out for. Pointers are always such a fun! /s

Else, it's not that much different from doing C# - sure the latter is more convenient to use, especially for game programming where you don't usually need the hardcore C++ stuff that much.

The main issues here were to learn how to interact with Blueprints and manage the network replication across both, blueprint and C++ code at the same time. I feel like this will always be a bit of a head scratcher. But at least I now have the basic process figured out.

For example, for the rocket controller, I create a Blueprint component and then set the rocket controller C++ class as parent. The Blueprint component takes care of setup and effects stuff, while the C++ part takes care of most of the tick calculations. The component can be attached to any actor with a skeletal mesh to make a rocket!

This could be fun in the future, to make it attachable to other stuff at runtime. But it would be quite a bit of extra work to have it properly set up, especially with regards to the control panel interface, which is not very well though out right now... :D


Rocket Controller Part II

I wanted to talk about one more thing here: getting the attitude in three dimensions and transforming it into individual controller inputs is not that trivial. So I took some (big) inspiration from this library - it's a really awesome open source library for control software of multicopters.

It takes some time to get into it, but it's almost exactly what I needed with a little bit of adjustment. Of course, then it takes some more time to make it work in Unreal Engine. For example, while the Arducopter library comes complete with it's own math functions, I wanted to use UE's instead. Since not all the functions exist 1-to-1 in the Unreal Math library, you have to really understand what the Arducopter code is doing and the math behind it. It's fun though to do a bit of Math again. Even though it's mostly just about rotating stuff correctly as you can see below.

I even learned something cool! You can make a rotation quaternion from a vector and the length of the vector with the MakeFromRotationVector() function. So by just supplying a unit vector of a direction multiplied with a length that represents an angle you can get the rotation, for example the rotation to get from the current thrust vector to the target thrust vector. That's pretty cool! And I understand better what Thrust Vector Control means now.

The good thing with the Arducopter library is that it has lots more stuff that can be used for position control for example, which is planned for the next update.


Outlook

Adding the position controller will be one thing. But first I need to fix the attitude controller. Since everything took so long and the update needed to be ready for the 1st of March release, the grid fins, flaps and RCS were quickly thrown in at the end without proper integration, or in the case of the ship RCS not even existing yet.

Of course, I could have just released the previous version on 1st of March and stuck to my original plan with this Ko-Fi goal, which would have meant finishing the update properly and just release the old version for the time being. However, the old version was from November/December last year. So I felt, it was a bit too old and the flying was too scuffed there. So better release a half scuffed version, but with much better flying.

I probably won't do such type of Ko-Fi goals anymore, at least not for quite some time (btw, I started Ko-Fi as alternative to Patreon. I should make a post about Ko-Fi/Patreon as well at some point^^)

When the controls are finished and I'm happy, I'll have a look at the flames and try to find another solution to get them more dynamic and faster and then, depending on how quickly all this goes, there is also an overhaul of the booster and ship model planned, but it might be split off into the following update, if the other stuff takes too long.

Overall I'm optimistic though that there will be slightly faster progress now with the Unreal version as the hardest stuff should be out of the way. Of course, the flame improvments might be hard as well, but I can always skip it for the moment, if it becomes too hard.

When the Unreal version is on par with the Unity one, it will replace it completely here on Itch.


Files

UNREAL-VERSION-StarbaseSim-Windows 810 MB
57 days ago
UNREAL-VERSION-StarbaseSim-Linux 904 MB
57 days ago

Get Starbase Simulator

Download NowName your own price

Comments

Log in with itch.io to leave a comment.

(+1)

Changelog:

2024-03-11

- removed a line that logged some debug data spamming the log file

(+1)

I guess I should add changelogs for patches here again. In the future also updates will have changelogs attached again to the devlog:

2024-03-09

- added first version of time dilation (there are still some issues with it, like mouse clicks not registering properly when game is very slow)

- fixed booster transport stand clamps not extending again after retracting

- fixed ship can't be spawned directly on booster, if you try to place it manually

- fixed observer jumping back to player after despawning something

- fixed attitude Z error discontinuity around zero leading to a twitch in the controller output (however, when setpoint is close to +/- 180 there still can be a bit of twitching)

- attitude Z is now displayed from -180 to 180 

- tuned some controller settings for better control during boost back with booster (this will also have some impact to controller behaviour in other circumstances)