Starship CEO
This is where messages will pop up
--:--:-- v0.1 · in development

Alive but dead?

Do I like building a game, solving problems, or do I just hate myself a little?

A few days ago, the entire 'place and build'-system landed, and ever since, I've seen my engineers all die, from hunger or thirst.

This problem somewhat coincided with me fixing a bug where needs got satisfied, even though the required machine or material wasn't available, so I thought this simply was the first time people on my ship could actually die from hunger or thirst.

It was. It wasn't, however, the problem: Even when I had enough water and food present, my engineers kept dying. And, pointing toward the real problem, only engineers. Not farmers, workers, the captain: Engineers seemed the only group of people dying, so I started following them, and as soon as I did, I saw the issue:

Engineers are the only people that can build stuff, so when I ordered a new layer of hull, they went out to do the actual work. They would go to the exact spot where the hull needed to be built, stand around for a bit, hoping I eventually get to adding an actual animation, and then the hull would be finished... And it finished "around" the engineer. So the problem was clear: An engineer went outside, built a hull at position 3,2,7, and once he was done, position 3,2,7 suddenly became inside, while the engineer still thought he was outside. Easy peasy solve.

It wasn't. It wasn't easy peasy, and it wasn't that they got stuck in the hull because they thought they were inside, though it took me a few days before realizing that.

Inside and outside regime

There is one pathnodegraphmanager that manages all pathnodegraphs, both inside and outside.

Inside the ship, it creates a node for every interior cell with a floor beneath it and connects it to its horizontal neighbors, as long as there's no wall between them.

Outside, the pathnodegraphmanager creates a visibility graph. Each cell where the ship 'turns' creates a node, on each surface, slightly outward from the ship. These nodes then check what other nodes they can see, and this creates a pathnodegraph. When an entity wants to navigate outside, it searches for the closest node it can see, and from there, pathfinding is, again, as simple as A* over that pathnodegraph.

It also means that 'Can I reach cell x,y,z' is as simple as comparing out pathnodegraphId's: Same id? Reachable. From here, pathfdinding is as simple as A* over the pathnodegraph and presto: Here's your path.

So all this time, I thought the problem was the inside/outside question: that an entity couldn't choose, or was choosing the wrong navigation regime. Because of this, I completely overhauled the "Am I inside?" question, which turned out to be a good thing anyway. For one thing, isOutside used to check whether there was a floor, even though having a floor has nothing to do with being inside or outside. We replaced the old rules with a much simpler one: you're inside when you're in a cell with a built interior, and outside when you're not inside.

This cleaned up the code considerably, but it didn't help my engineers get to their food in time. They kept dying, even after thoroughly checking the inside/outside logic.

So what was it?

Even under the old, incorrect rules, engineers knew they were outside. That had never been the problem. The problem was that they were outside, and therefore using the outside navigation regime. As soon as the hull was built, however, all outside nodes became invisible to them.

This was far easier to solve: if an outside worker can't see any outside node, simply let them move to the closest one. From there, A* can take over again.

That left one more problem, small to describe and quite big to solve:

How do people move from one regime to another?

Navigable entities

Somehow, I had to be able to connect the two pathfinding regimes. Up to then, this was done pretty clumsily, with some special hardcoded stuff that only applied to airlocks. Not satisfied with all that special casing, I got to thinking: What does my airlock need to do? Well... It needs to connect to the inside pathnodegraph on its inside cell, to the visibility graph outside, and allow people to move straight through a hull piece. Trying as much as I could to come up with a general solution, I wrote the CreatesNavigablePath capability: I can author an entity, give it a navigable path, allow nodes to connect to already existing nodes inside the ship, have the pathnodegraphmanager include the paths of placed entities in its created pathnodegraph and suddenly, people can move in and out of the ship. A CreatesNavigablePath-entity has options to create nodes and paths between those, it can connect to a node inside the ship, and it authors a cost.

Not just that: It also allows me to author stairs, lifts, ladders, rock climbing walls, a recreational maze, or a large engine with a workplace on top of it that would otherwise be unreachable. I now even author doors as a CreatesNavigablePath entity, as it allowed me to remove the special code for doors from the pathnodegraphmanager. Any wall, with or without door, now blocks navigation: Doors simply add a navigable path that reconnects the nodes on either side. In the case of the airlock, the inside node connects to its neighboring nodes. Outside, its node is simply sticking out a bit, seeing and being seen by the visibility nodes that line the outside.

In the end, engineers not being able to see any outside nodes made me clean up the inside/outside question and it helped me lay the foundations for CreatesNavigablePath, which suddenly became one of the most powerful capabilities in the game, while greatly simplifying the code.

Not bad for a bug that never existed in the form I thought it did.

← A bit about GameObjects Why is a cat like a condenser? →
All entries