Yes, but what about a Hex Grid?

Some of you may have noticed my I get carried away when I’m bored" post, where I worked out the breadth first algorythm myself because I didn’t have access to the lectures…
Today, same boat… No videos
Well, I started wondering how all of the techniques we’ve learned so far would apply to Hexgonal tiles I knew the BFS algorythm would work on it (you just have to add the directions), but how to work out the grid, and the automatic placing and labelling…

The first step was creating the hexagons… Thanks to Unity giving us ProBuilder for free now, it didn’t take too long to work up a reasonable Hexagon (I created a cylinder with 6 sides in the pro builder… well, two of them, one for the top, and one for the rest of the body). That was the easy part. Next came some dramatic changes in the math…

You see, the factor on a hex grid isn’t the same as the factor on a cube… gridSize=10 won’t cut it. It turns out the x spacing and y spacing are quite different on a hex… And of course, your script needs to figure out if it’s an even column or an odd column…

Once I worked out the math, after SEVERAL false starts, I finally got Hex tiles moving and labelling themselves in the editor. Since I designed my program so that all the in game elements are descendents of “Gridtype”, simply checking the “Hexagonal” boolean was all it took to get everything to conform. (An enemy, actually using the same enemy as the regular grid) has no idea if it’s hex or not, it doesn’t care, that’s all handled by its base class Gridtype.). Same with the spawners.

So here’s my example of some enemies perusing my shiny new Hexagonal grid.

5 Likes

Wow, great effort.
Why do some of the enemies go to -4,-1 and some -4,-2 s their first move ?

Because when their path was being calculated, 4,2 was taken. When an enemy occupies a tile, it marks the tile as “containsObject”. Each enemy requests a new path from the pathfinder when it’s created (or if it’s blocked on its current path).
Actually, since every enemy on the board “blocks”, the resulting paths make a lot of detours in this one. For later versions, I added an “intelligence” tweak… to determine how often it will recalculate the path… a smart enemy will recalculate every frame. A dumb one will recalculate not so often, and might take the long way around because when it was created, it thought it was blocked, and never recalculate unless it hits a tile where it’s blocked. (Any time an enemy finds it’s blocked, it recalculates).

For extra fun, I’ve added movement costs…
My Dykstra solution

Hey Brian,

Are you relaunching pathfinding when the find out the way is blocked? I’d like to do the same, but I can’t quite work out how to do it. I’ve got it organized so every unit has a pathfinder script on it, which it calls the RequestPath() method to, which then returns a path. I have a path.Clear() as part of that method to make it reusable. However, if my guys try to get a new path, the FollowPath CoRoutine takes issue with the change in data. Stopping and recalling the CoRoutine doesn’t seem to work. How’d you deal with that aspect?

Also, do you have a case where the path can actually not exist? I’d like to do that to, so they simply wait for a float value amount of time and then try again. Or, I suppose, ideally get as far as they can and then wait for a possible route. Can’t quite get my head around that either, any insight in how you got that re-pathfinding working would be appreciated!

My findpath returns a path which each enemy caches. If it is blocked, it just asks for a new path. If there is no valid path, it waits a turn and asks again. To change things up, it asks for a new path anyways after every few turns. (Creates diverse behaviour)

Thanks for the quick response!

Are you using an IEnumerator to follow the cached enemy path? That’s one of my snags, is trying to reset that Co-routine always reports an error about data values changing. That’s using StopAllCoroutines() and a new call to start the CoRoutine.

My other question, if you have a second, is where you’re catching the failure to find a path. Do you just have a separate cancel-search method if all waypoints are explored but the end waypoint isn’t found, like the HaltIfEndWaypointFound() in the course videos?

I created a PriorityQueue buffer, Each enemy enters the buffer, with it’s Priority being the current moment + it’s speed based offset…
The PriorityQueue finds the next enemy in line, and tells it to take a turn. An enemy’s turn consists of:
CheckForPath()
If NoPath, return to the queue
If path found, move one position on that path, then return to the queue…

Privacy & Terms