Tower Defense update. Blocked Enemies

I think I once said I had no technical challenges left. That’s not 100% accurate. While there’s nothing I have to look up in the engine on how to do, there are still a few technical design decisions left that I’ve been avoiding since I started. Here are those three technical decisions.

  1. What happens if you build towers and the enemies can no longer reach the exit?
  2. What to do when you try to build a tower and enemies appear where you want to build? Note that the game does not pause while you build.
  3. What to do when an enemy reaches the exit.

The third one is a critical part of the game and I’m still trying out different things. The second one could be handled with a delay and disable building more towers until enemies move away.

The first one is the one that I really didn’t want to tackle. At first, I tried to build an internal map, but that got complicated real fast. Then I realized a few thing. First is that you can only build towers on one kind of Actor. These are called PathActors in my game. You can disable building towers on them and still use them in the level for the enemies to use. These are 8×8 tilesets. You can reduce their size with a simple size property. And you just place them side by side. All tiles in my game are 100cm (or 1m). So it’s easy to build an internal graph for this part and connecting them together is just checking what tiles are about 100cm apart. Easy.

Next are the irregular shapes. There are custom shapes and single tile components that can be grouped together into a single actor. I tried a few different things again it just got complicated. Then I had my second realization. Since you cannot build here, only the jointing tiles need to be specified. So I manually added a spline component to these with an endpoint at each end of the path. You can even add more splines if you’d like as long as spline points overlap as connecting points. Again, easy. I just scan for these splines and join them up. It’s a bit of manual work to add the splines, but it just makes thing so much easier.

I had a few issues still and drew the internal map. Here is an example (after I fixed my issues).

What is the point of this map? How is it used? I hooked this up to an AStar navmesh. When you want to build a tower, I set a node as blocked (the blue spheres) in the graph and check if the enemies can go from each entrance to their exit. If not, then you can’t build there. In fact, the menu and the selection square won’t even show up.

This took three days to implement. And this was quick because I had to generate the map from the actors in the level. I didn’t want to generate the maps manually. I also reused the AStar code from my first game.

I also learned a few things about navigation meshes. First, you don’t need to spawn one yourself. Instead, you go into the project settings under Engine/Navigation System. Then go to the Agents section and add an agent for your navigation mesh. You can select your navigation mesh class there. Do not remove the main mesh. That’s the one you will use inside your game.

One important thing is that registering a navmesh IS the same as adding it to the list of supported agents. So don’t register your navmesh. It’s not necessary.

To do an internal query, it’s rather simple. You grab the navigation system and do your query there. Like this:

FPathFindingQuery Query;
Query.StartLocation = StartTile->Position;
Query.EndLocation = EndTile->Position;
Query.bAllowPartialPaths = false;
FSharedNavQueryFilter QueryFilter = MakeShareable(new FNavigationQueryFilter());
Query.QueryFilter = QueryFilter;

UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
check(NavSys);
FNavDataConfig config = NavSys->GetSupportedAgents()[2];

FPathFindingResult Result = NavSys->FindPathSync(config, Query);

if (!Result.IsSuccessful() || Result.IsPartial())
  return false;

Note that this is when you don’t use a path following component or a in-level navmesh and just want to do a simple path query.

You select the navmesh you want to use with NavSys->GetSupportedAgents()[n] where n is the index of the agents listed in your project settings. Mine was the third navmesh. The first is the one used in-game by the enemies. The second is used by the UFO’s for the carrier tower. And the third is to verify that you can place a tower.

That’s one issue resolved and it works great. I added some flags that are cached so I don’t need to recheck the same tiles repeatedly. When you build or remove a tower, those flags are erased.

Next I have to finally decide what happens when an enemy reaches the exit and start putting some levels together.

Posted in Uncategorized.

Leave a Reply

Your email address will not be published. Required fields are marked *