Infinite Loop in Blueprint slash Is There a Better Way to Be Doing This?

Quick overview first. Doing a simple 4x-style game with most of the scripting contained with a single repeated tile class that’s overlayed over a map. One thing I’d like to be able to do is activate neighboring tiles but as each tile is essentially an island unto itself I had to come up with some way of determining their relative positions so that one tile could determine which tiles are its neighbors in order to toggle their states to active.

So my method involves three arrays. The first is an actor array (TileStackPort) containing all the instances of the tile in the game world, the second and third are integer arrays used to store the x and y coordinates of all potential neighbors to a tile. The first step uses a nested loop that goes through and adds all potential matches to the x and y arrays. After getting those it goes into a tri-nested loop with the actor array comparing each tile member’s own x and y coordinates to each of the values in the x and y arrays. If there’s a match we then use the actor loop’s array index as a reference point to activate that tile.

The system works, it’s just that attempting to use it with any activation radius size larger than three causes an infinite loop in blueprint detected error message (three also makes the sound cut out for about a half second while it chews the loops). It’d be much easier if I could simply sort the tile stack array by a particular property but that option doesn’t seem to exist that I could find so this is what I improvised. Is there anything could make it a bit more graceful?

A couple thoughts, not sure if they will help your particular situation or not:

When i was playing around with a top down strategy type game (tower defense in my case), I just used collision to detect neighbouring tiles. Each tile had a collision volume on it at a certain radius, and I used GetOverlappingActors I believe (which allows you to filter by class type) to find any nearby tile.

Alternatively, couldn’t you just loop through the array of tiles, and compare their location to that of your city tile, and if the distance between the two is under a certain threshold, they are neighbours?

As for the infinite loop, If you wanted to keep this setup it might be helpful to detach all of the loop execution pins, and reconnect and re-run them one at a time until you find the one that’s actually causing the infinite loops.

Also, In the last two for-loops, you use ActivatePotentialXVals Length as the last index, which I believe will give you an invalid final entry (if the length of the array was 5, the final index would be 4), you should be using the LastIndex node there I think.

Adding a collision volume surrounding the tile definitely seems like the easiest way to go. I’d considered using tile world position and distance as a way to automatically grid everything but come to think of it that would work for this job too. I was thinking I’d need to cast a ray and swing it around and see what it hits to do the job but all I really need is distance…

I’m sure it’s not actually an infinite loop, it’s not like anything changes about the setup from when it works to where it doesn’t other than the value of ActivateRadius going from 1-3 to 4 or greater and how many sets of numbers are added to the int arrays as a result. It’s just running into some loop recursion threshold. Not that that’s a good thing, of course. Think I will change it to something distance based since that seems most straightforward for retaining the ability to activate tiles from a variable distance.

And yeah, I should’ve remembered to make it array-length minus one there. UE4 doesn’t seem to care if you ask it access a non-existent array index and there’s no presumably 0,0 tile to ever get matched to anything but even still, bleh.

If you had an infinite loop the editor would lock and you would have to go to the task manager to close the editor. Most likely you are hitting the iteration limit and it exits out of the game and spits out a log error. If this is the case you can raise the iteration limit to ~2 billion in the project settings. This will at least get you around your current road block.

Longer term though, I think you are going to want to take look at your data structure. I used to hit the iteration limit all the time, but that was for in depth map generations.

What I do is early on in the process I fill a struct array where each tile stores the array index of each of it’s neighbor tiles. So this struct has North, Northeast, Southeast, South, Southwest, and Northwest. If I want to find out what is North, I take my current tile’s index, get the neighbor struct array, pull the index for North, and then plug it into whatever other array I need to check. The key is to have all your arrays aligned with each other, which is however you have set up your data structure. I emulate 2D arrays in a normal array. If map size is 10, index 0 is the bottom of a column, and 9 is the top. 10 is the bottom and 19 is the top of the next column.

You could probably get a better approximation of 2D arrays by using a struct, but it isn’t necessary. More importantly you need to operate in a data structure that makes sense to you, because you are going to be spending a lot of time in it working on pathfinding and hundred other systems for a 4X.