Ahoy, everyone! Captain Marek speaking. In this diary entry, I’d like to tell you how we designed systems for connecting machines with conveyors and pipes (we call these “transports”) and how we improved these systems to be more powerful and easy to use. This post is a little bit longer but feel free to skip to later sections to see the results!
History of transports
I’d like to start with a little history about transports. These were in the game from the very beginning, even in our 2D prototypes! They were designed to allow transportation of materials between machines. And from the time they were implemented in 3D, we were able to place them at different heights to be able to go over/under obstacles or other transports.
A very early 2D prototype (left) next to a very early 3D prototype (right) of machines connected via transports. The red and green cubes are input and output ports.
However, we noticed that building transports one segment at a time was not a very enjoyable activity, especially when there were other transports or obstacles involved. Basically, transport building turned into a 3D puzzle mini-game and it was frustrating. We felt that the player should not worry about finding the way for transports.
So, roughly a year later, we have implemented the first version of transport path-finder that is able to find a path automatically! You just selected a starting point and goal, and the shortest-path transport was built! This has totally changed how a transport building felt and it became a very satisfying experience.
Fast forward to a few months ago, we were on our 3rd implementation of transport path-finder that is now much more optimized, has features like snapping to the closest port (ports are places where transport can connect to buildings), and allows building transports with real-time preview. But there were still issues.
During our pre-alpha we noticed that many people were having issues with building transports in more complex/crowded scenarios, and they could not figure out why certain transports couldn’t be built. This was hard to watch. After reviewing many videos and streams we concluded that nearly all issues were caused by pillars – supporting structures under transports that make them supported when built at height. The rules for pillars were:
Every transport that wasn’t on the ground had to have pillars at the start, end, ramp start/end, and at turns. Straight segments couldn’t be longer than 7 units without being supported by a pillar. Additionally, the maximum height of pillars was 3 units.
These rules were ensuring that one couldn’t build transports too high, over obstacles, or over large holes in the terrain. And this worked very well. The issue is that pillars were also obstacles, which backfires when you start to split and merge transports. Let me explain.
If you want to split a transport, we take the original transport and split it to two by cutting out one piece, and replacing it with a small entity called “balancer” which is able to distribute incoming and outgoing products. The remaining pieces are now two separate transports. But due to the pillar rules, we had to place two pillars at the start/end of the new sub-transports around the cut. If these were blocked, you couldn’t split the transport.
Connecting transport is not possible due to the second transport below that blocks a new pillar that would have to be built after the split (left), the connection is only possible a little farther (middle), notice the extra added pillars around the split (right)
And even if everyone knew about these rules, the pesky pillars were limiting what you could do with transports. Consider a bus layout shown below where we need to just branch products to connect more machines. Since every transport needs a pillar right after the split, you have to space them out by one, otherwise, it is not possible to branch them.
Connecting to staggered transports was not possible due to the extra pivots next to the connection (left). It was possible to space the transports to achieve the intended design (right).
Finally, the player had no control over where pillars were placed, but their position was sometimes important. If a pillar was placed right in front of a port or other place where you wanted to route a transport, tough luck. You could redesign or try to destroy and rebuild the transport with a blocking pillar hoping that next time the placement will be better. Not a great experience, and while you were trying to figure this out, you ran out of diesel and maintenance – game over, oops!
New transports and pillars
After many brainstorming sessions, it was clear that we need to somehow address the issues with pillars. How awesome would it be if the pillars would not block other transports at all? We tried to just remove all pillars but that looked terrible, levitating transports are not fitting our realistic world.
The next option was to make pillars shaped in a way that they don’t interfere with transports. We thought that four poles in the corners would visually look ok. This idea was feasible, but our game internals could not handle two overlapping entities, such as a transport going through a pillar. Additionally, our awesome transport path-finder would now need to be able to do these tricks with pillars colliding with only non-transport.
Long story short, we have rewrote occupancy representation to allow overlapping entities such as transports and pillars (mentioned in entry #3), completely rewrote our transport path-finder to handle new pillar rules, designed new pillars that do not obstruct transports and balancers, and slightly changed transport shapes to accommodate pillars going through them.
Additionally, the pillar placement rules were relaxed as well: Every piece of transport must have a pillar at most 4 grids away. This means that transports do not need to have pillars at start, end, or in turns anymore making their placement even less restrictive.
However, these changes brought more complexity to the visualization of the new non-obstructing pillars. We wanted to make transports look attached to pillars where appropriate. Transports have many different shapes like turns, ramps, turns in ramps, and we needed a different attachment for each case. Unlike transports that are procedurally extruded mesh over a 3D curve so we need no 3D special model for them, attachments were designed and modeled by hand for each case.
Previously I have shown you how bus-style transports were hard to build due to pillars. Assemblers were usually painful to connect since they have three inputs right next to each other. But with the new pillars, it just works beautifully!
Moreover, you can even build transports on top of each other now!
Connecting transports to buildings is now easier as well. While you can start or end transport by directly clicking on an arrow next to a port, hitting that tiny arrow can sometimes be quite hard. We have improved this by snapping to the closest port when you click on a building during transport construction.
Before, starting or ending transport while hovering over a building resulted in an error (left). Now (right), hovering over a building snaps a transport to the closest matching port.
When searching for the shortest path, there are often many equally good paths, especially in cases without many obstacles. We have improved the way to switch between the solutions.
Another new feature is connecting transport to already existing ones at an angle. Previously, you could only connect to a port but the end-direction of existing transport could not be changed. This was sometimes limiting. Now, if you connect to an existing transport, its end-direction will change to match the new one.
Before, a direct connection was not possible. Now, this is possible and the end direction of existing transport is changed to match the newly built transport.
We have also added the option to hold SHIFT when building a transport to instruct the path-finder to build the transport in a straight line. This will help to keep your factories neat!
The new path-finder is really awesome. We have mentioned in diary #2 that it is roughly 100x faster than the old one. I think the techniques and optimizations we used there deserve their own diary entry. In the meantime, just enjoy the speed of transport-finding!
Even though we made a huge amount of improvements we are not done with transports yet. One of the frequently requested features is a partial deconstruction of transports. It can be annoying that in order to shorten a long transport, you need to destroy the entire thing and then construct it again, but shorter. We will be adding this soon, but it won’t be in alpha, sorry!
Another feature we’d like to add is the ability to transport mechanical power via shafts. Currently, machines that use mechanical power such as turbines and generators can be only connected directly to each other.
Finally, we were hoping to eventually allow vertical transports for pipes. Currently, pipes can be built under 45 degrees up/down but being able to go vertically would allow even more freedom in factory designs. This was previously not possible but since we have new transport infrastructure and pillars it is possible now.
Whoa, this diary post end up being way longer than anticipated! Thank you so much for reading and get ready to test all these features for yourself during the alpha that will be out in less than a month! In the meantime, let us know what you think on our Discord server!
Captain Marek out.