Art of the Rail cover
Art of the Rail screenshot
Genre: Simulator, Strategy, Indie

Art of the Rail

Devblog #4: It's been a while, but lots of progress

So it's been quite a long time since I did an update on Steam, and internally our corporate side has been begging me to provide an update for you folks. So here it is!



Note: First two headings are general commentary, skip those if you just want game info



Background


If you just want to keep up-to-date, our internal processes automatically post "commit messages" to our discord. This means that you can see changes live as I make them to the game. I put pretty detailed commit messages so you can get a sense of the changes I am making and often some degree of why.


It's been a while



Firstly, apologies for not posting updates here sooner. This project started as a COVID lockdown project for me (Dean), so it's been a core passion for me. Unfortunately COVID also bought with it some pretty crippling social anxiety. I'm in this weird place where the reason I make games is to see people playing them, but I began to dread the bad possibilities from some of their reactions - the very reason I made games in the first place. Hard to explain, but hopefully that gives some rationality.

Additionally I'm not really very happy with where Steam is as a platform for my kind of games. When I made DayZ, I would stay up 18 hours developing, push updates, and then fix bugs. In terms of community and developers we were pretty much one unit. The lines between the two barely existed. It was chaotic, but it was an amazingly creative environment and pretty much the whole reason I make games. While Steam has made efforts to try and help with this process, I'd say its just not a good environment for the early creative stages of a project.

Steam release options like Steam Beta





I won't release on Steam, even in early access, until I'm really sure of the data structure and the core loop of the game. The priority at the moment is finding the core group of players who really want this kind of game and are prepared to pay for it. I had discussed with Valve using their new Steam Beta program, which allows users to register interest in a game and allocates keys randomly to them. It's a cool idea. But the problem is you end up getting feedback from people who otherwise wouldn't have actually bought your game.

This can mean someone ends up trying your game and then proposing the game should be something completely different. You end up having to heavily manage expectations about your game and only attract the people who want that experience. For similar reasons, I would suggest that Steam Reviews are largely a measure of expectations being met rather than a true guide of quality.

Art of the Rail will come out on Steam when it is ready, and it is totally worthwhile Wishlisting and Following our progress, but more regular updates and early playtesting are more likely over on our Discord.


Game Development Progress





While I might not have been posting here on Steam, I've been pretty steadily working on the game. One of the key things I want to do before any wide distribution of keys is to get the data structure really locked down. I mod a lot of games and with many of those games the developers had to make major changes to their data structures which caused major work for a lot of modders and customers. Being a very niche game, this game will live through mods. This means my main role is to get the right data structure so that it can survive through the game's life to support mods as best as it can. Additionally, I wanted to make sure stability was rock solid.

The rise of RocketNet



AotR (Art of the Rail) is focused on providing scale, which I feel is neglected by many games today, and is a core part of tycoon games of the past. So the key focus has been to meet that scale on all sides. Our special R&D team (called "Enterprise" internally) took my proof-of-concept for a highly optimized networking approach and made a new system called RocketNet. This stuck to a "first principles" approach. Everything on the internet is sent via an "array" (think: collection) of bytes (well, technically speaking it would actually end up as bits but that's not strictly relevant here). So instead of "wrapping up" game data as "messages" (think of them like emails), we write those bytes directly into a collection, zip up the collection, cut that collection up into segments (1200B), and send those.



The results of this, when implemented in our other game Stationeers, were staggering. It removed a lot of the convenience of using network messages, and required a much higher level of programmer understanding, but the scale achieved was two or even three orders of magnitude better.

So a huge focus for AotR has been improving the multiplayer stability over the last year, working with our Enterprise team to refine this technology. Most of this technology is written in C++ and "injected" into the C# used by the project. The Enterprise team has even been working on this injection process, called the "interop layer" - looking at how to make this more and more efficient.

So what does all this mean? It means that AotR is looking to support very high numbers of players, and the limitations around player numbers should then more be a question of general bandwidth. Hosting an AotR dedicated server with a 1GB connection, should be able to service a lot of players.

Graphics & Game Optimization



With multiplayer optimization going well, the next bottleneck was the game itself. I ripped out the old "fenced" threading system and replaced it with pooled threads, taking the broad approach of Unity's ECS but rolling my own. This was because Unity requires you to make your memory safe, which often defeated the goal of wanting a much better framerate.

Initially I had these fenced threads running fully concurrently with the rest of the game. But this made the project extremely complex and the smallest mistake on my part caused huge problems. This meant that the vehicle thread would be moving vehicles while the rest of the game was trying to do things. What I ended up doing was having multiple instances of vehicle threads, but getting them to work on the next frame's data, and then forcing the game to wait if they weren't finished before starting the next frame. This gave the benefit of concurrent activity, scaling with the quantity of cores on your system, while keeping the data certainty of having a single thread state for the game itself like most games. The end result was excellent, so much so I was able to group a lot of things together as well as provide much more stability.

Customizable Corporate Liveries



Initially the game was targeted at eight players max in a session and using a texture array per vehicle to manage the color schemes. This meant that each vehicle or building that wanted to display company colors had to have these eight different textures. As the number of vehicles and buildings increased, so did the number of textures. Additionally, during game start the game captures pictures of these buildings and vehicles - often in different cargo states - so that it can draw them efficiently later. This increases loading times dramatically as well as memory usage.

So this was replaced with a masking shader system. Instead of different textures for different company colors, there is a base texture colored white with a mask texture that shows where a primary, secondary, and stripe color would be applied. This is then used in a composite nature when rendering either the vehicle in the scene or the UI textures for buttons and windows. This meant two things, eight textures became two textures, and instead of being limited to eight company colors, we effectively get unlimited company colors with many variations of primary, primary and secondary, primary and secondary and stripes, primary and stripes, and so on.

Batch Rendering & Virtual Objects





With the success of the existing method of rendering things in "batches" I expanded this significantly. Batching involves sending the mesh to the GPU once, and then sending it all the "transforms" of how you want it drawn, being the position, rotation, and scale. This is efficient but especially so with how AotR draws objects. Traditionally, you might send a mesh for a building to the graphics API, saying "please draw this here". Most game engines will try to be smart and batch stuff together, but it doesn't always scale well in a dynamic environment. So AotR is very deliberate about this. Most objects are actually a "constellation" of a group of "visualizers". That is, broken into small meshes which can be used across many different objects and then batched together. Cities Skylines follows a similar approach. AotR even goes further and in many instances does not have Unity (the game engine) objects at all, having them as pure C# data constructs and handing them directly to the graphics API for rendering.

There still needs to be some improvement here as in my many thousand vehicle test the game runs at 90 FPS except in certain views when a lot is on the screen. There are still many easy wins for consolidating the batch processes together. However, it still took me months of playing the game to get a save game big enough to get the FPS to drop from 90 to the occasional 45 in a certain view.

City Development





Cities have been a highly requested feature internally. It's something I have been chipping away at alongside other improvements. This pushed my batch rendering system even further. Now chunks themselves are able to batch render things, such as straight pieces of track or city roads. I've also created the simple method for the roads themselves to expand and Petr, our amazing artist, has made a massive amount of content to allow the cities to grow. The cities will also be able to make use of the corporate liveries shader, as it will allow the buildings to have slightly different colors but be rendered in the same batch. Given the need for scale, this is incredibly important for performance reasons.

Industry Cargo System



I redid the industry cargo system to be completely modular and entirely data driven. This fits with the development philosophy as having as much as possible driven by game data, and having that "core" game data loaded just like a mod would. This means, essentially, anything done data wise in the game is open to modders. Production for industries is data driven via rules, and this has opened up expandable industries based on rules, as well as bonuses based on rules. Providing a lumber mill with petrochemicals increases its efficiency temporarily, but having delivery of produced goods at above 90% on a rolling six month average would cause that industry to expand its production.

Terrain fixes



Originally it wasn't intended that you could modify the terrain under a track. But I never actually wrote logic to stop that happening and it became surprisingly satisfying to modify and improve the terrain underneath the track. However, the logic for terrain and track generation never intended this to be supported. There was a lot of weirdness caused because terrain meshes were not being regenerated immediately upon change, as their performance wasn't great. It took roughly 50ms after a change for the terrain mesh to regenerate itself. Some of the data in this is necessary for the splines (tracks and roads) to be generated properly, specifically the terrain "normal" (direction a terrain point on the map is facing, if it is flat it would be straight up). So the spline mesh generation would then be delayed until after the terrain mesh regenerated.

This became really complex, convoluted, buggy, and messy. Lots of edge cases and possibility of race conditions. I completely removed the terrain generation system and made a new one. This new one was so performant that terrain mesh could be done on demand when needed. This means that when a mesh is required to give data for a spline, the game can regenerate the mesh immediately and then do the spline. It doesn't do this by default, allowing itself a little time to generate a mesh if it's not needed immediately. This solved a lot of problems and also made the code much simpler - which means much easier to maintain.

Load Balancing bays using custom tags





Similar to tags in games like Factorio, you can tag vehicles and bays and then use those to do your own load balancing. This is in addition to the regular tools such as setting a bay to a particular cargo type.

Terrain Tool Improvements







With the above fixes I was able to improve some of the terrain tools. The most popular tool internally has been the ramp tool. Placement in general was improved with keys to lock the cursor to cardinal directions as well as a height lock key.

Devblog #3: Refactoring Multiplayer and Optimization

Over the past six months things have been busy for both the project and myself. Petr and Paul (our two artists) have been hard at working making lots of new content for the game, slowly chipping away at the industry tree for the game. I've been focused on a mixture of running our studio and setting the groundwork for Art of the Rail's tech architecture.

Multiplayer Performance Improvements



One of my biggest concerns prior to release was the performance of multiplayer. I just wasn't happy with where it was at, I was already encountering serious bugs and I didn't have anywhere near the number of vehicles I wanted. So I focused on a major rework. It was really very substantial. This resulted in me redoing entirely how updates are sent to clients. As part of this I also did a lot of optimization and bugfixing, improving how clients connect and files are transferred. Overall - I'm very happy with the result.



Optimizing Rendering/Movement for lots of vehicles



Additionally I wanted to further improve the rendering, to ensure that I really could display lots of vehicles. I don't feel like many games really achieve the level of scale I wanted from the title. This involved improving how vehicles are rendered, removing how trucks calculate whether to stop or not, and also how garbage collection (an issue with C#/unity games) was handled. I achieved great results in most of these, although the truck collisions, while now very performant, have some edge cases I need to deal with.

I also changed how vehicles move along the splines, making it more performant while solving some jittering issues. There's still a little jitter, I think related to a mismatch between timing of my thread (which moves the vehicles) and the game thread (which draws them). I'll ask some of our super programmers at the studio to give me advice on this.

Assigning Allowed Cargos





I also played around with new mechanics. One I am very pleased with is bay and cargo assignments. I started with the vehicles, allowing you to restrict what can be loaded. Let's say a wagon takes all kinds of ore, you can say "only accept coal". These settings are copied when you clone a vehicle. Then I expanded it to bays, making it really great to micro where you want road vehicles especially to go - allowing you to have a dedicated bay. I need to work on the UX for it a bit, but overall I think that direction really fitted well with wanting to make the stations more a "thing" in this game than others in the genre.

Next steps





The big next focus is going to be layering in cities. This will also include work on alternate transport options such as trams. I also want to work more on the multiplayer bugs, such as jerky vehicle movements. I've been testing mostly with dedicated servers, trying to improve how it runs to make it really easy to host.

Devblog #2: Modding and Filestructures

Much of the work for the past few weeks is a bit harder to see directly in the game but is incredibly important as a foundation for a solid game in the future.

New Content


https://sketchfab.com/models/0f59fa935948494d877f63b0f4e28fe2
Our two artists have been feverishly adding more content to the game. This ties in very well with the filestructure improvements detailed above as it is becoming much easier to add things to the game.

This new content includes new trains, new industries, a bus, a van; and much more! As we proceed forward we will be continuing to add more (and deeper) industry chains. This update includes the Iron Ore mine (seen in the sketchfab scene you can explore above), as well as the Steel Mill. This steel will be used for helping to grow towns or you can take it to an auto factory to make cars.

Our amazing sound designer (who also dabbles in sound programming) has been hard at work making amazing music tracks for the game. There is, I think, fourteen of them now and he really has done a great job.

Steam Integration


https://steamcommunity.com/sharedfiles/filedetails/?id=2536698993
I now have full steam integration, and in fact we have our first steam workshop item included below - a cube covered in a mapping texture that makes an annoying beeping sound. Just what you always wanted? Perhaps not - but it does provide a basic test of how well modding works. You can make new vehicles, new cargos, new industries - new everything! Which is what I feel the lifeblood of a game like this is.

I've also added the first pass of steam stat recording that I will be able to use for a whole bunch of achievement mapping. I'm struggling on the server front though, as some features of the steam server API only seem to work when the game releases when it comes to running the dedicated servers.

I'm making the game so that it runs really well whether you run it via steam or not. The game will detect if you are using steam (and own it), or using discord, and react accordingly. However, if you run the game without steam it will still run just fine - it simply won't be able to use steam features like workshop and etc. This means the game has absolutely no DRM at all.

New Physics for Vehicles


Because I want to run tens of thousands of vehicles, we can't really use the physics engine provided with Unity. it's just a bit to high of a cost for the amount of wagons and wheels and all that I want. This project has been about scale, first and foremost - so I've tended to develop custom approaches specifically designed for what I need so they are as lightweight as possible.

However, the physics approach I had for moving the vehicles was not great. So I made a new one, and even based it on more true to real-world calculations. This takes into account the mass, tractive effort, power, slope, and many other factors. It's also even more optimized that it was before.

Multiplayer Changes


With the new physics rework I had to change how vehicles were handled in Multiplayer. This was a bit of a mixed bag, as I fixed many things. Unfortunately... I'm still plagued by an issue where framerate differences cause the dedicated server running slower, to move the vehicles slower. This "shouldn't" happen as the threads moving the vehicles take into account framerate. But, nevertheless, it is happening.

Good news is I "soaked" the dedicated server for the last 30 days, running the game well into the 2800's. Game ran fine, no memory leak. So I'm very happy with the core stability of the game in that sense. It's also already quite well optimized on the network bandwidth front, but I'll keep testing that just to make sure.

New File Structure


While the game is made using the Unity Engine, much of the game happens and is loaded outside of the direct engine. This includes all the data and files for the game, such as models, textures, sounds - and even data files defining what stuff is.

Previously all this data was located in a special folder, and "core" game data was loaded from it. The cool thing is - to add content to the game I do exactly what you will as a modder! This makes supporting modding really easy, and gives a lot of ability to modders. There is very little in the game that is "hard coded" so any kind of content at all in the game can be changed.
The downside of this... is loading times and disc usage. The project had ballooned from roughly 200MB to nearly 1GB. The "folder" based structure was also presenting issues for transporting mods and save files.

So I implemented a package system that allows game data and files to be loaded either directly from a folder or from a "modpack" which is really just a folder zipped in a special way. Oh and while I was there, I added Steam Cloud and Steam Workshop support too!
The game is now back to 250MB in size, and loads much faster. You can either have mods in the dedicated documents folder for the game, or subscribed via steam workshop.

Settings and boring stuff


Over time I've been constantly refining and refactoring a lot of boring little things - like the settings system, console commands, and startup parameters for the game. While not very interesting - they will help a great deal for people to use the game when it comes out. Console commands can be used to debug the game, or even control it when running a dedicated server. Startup parameters are really useful for those running many dedicated servers on one machine (such as server providers).

Okay well, that's it for this month. See you next month for some more great progress! Please do wishlist the game, and post your comments or questions below and I'll see if I can answer them.

Devblog #1: Testing... lots of Testing!

The key focus on the project so far has been to really ensure that the game can scale. That's been very important, so that's meant a lot of testing followed by refactors. Not only do I need to ensure the game is able to render thousands and thousands of objects (sometimes in multiple cameras!) but I need to be able to synchronize all their states; both to disk and any clients!

Progress on Modding Tools



Additionally I've been slowly expanding the modding tools available for the game. All the game data itself is actually loaded as a mod, so anyone will be able to do this. But I'm also putting a lot of editor tooling in the game to make it much easier for people to make mods.



Dedicated Server Testing



I've been testing quite a lot with dedicated server files as well. Currently issues are mainly occurring due to FPS differences between clients and servers. Solving this is causing me a slight headache! Nevertheless at the studio we have been having some successful (and very fun) multiplayer sessions.



New Trains, Industries, and More



We've got Petr and a contract artist working on lots of new content for the game as well, so we have a lot of new industries, trains, and vehicles already flowing into the game. Expect to see more and more in the screenshots as the weeks go on.



Next Steps



Lots more testing. Performance is excellent and network bandwidth will support very large numbers of units. Some more work needs to be done "virtualizing" the splines more. I've tested over 4,000 of them with no issue, but realistically the game needs to support over 60,000 of them. Additionally, some rendering cleanup in terms of occlusion culling is important too.

The big ticket item is to continue the early stage work I've done with cities. Expect to see the cities in all their glory in the next update!

https://store.steampowered.com/app/1286190/Art_of_the_Rail/