Absolute BS infinite loop error...

Aha, that screenshot explains why you’re hitting the limit. I feel like this is another not very well known little quirk to using blueprint. Let me demonstrate with a small example: Pure vs. Impure posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Unfortunately the execution pins on the two functions below the Tick Event don’t render properly, try moving the Print String node between both “Pure Function” nodes, that fixes it for me.
If you paste that into a test blueprint based on Actor and reduce the Tick Interval you’ll notice the following (or similar) output if you drag this Actor into a level:

LogBlueprintUserMessages: [BP_PureImpure_2] PureFunction called
LogBlueprintUserMessages: [BP_PureImpure_2] Using PureFunction result twice (1)
LogBlueprintUserMessages: [BP_PureImpure_2] PureFunction called
LogBlueprintUserMessages: [BP_PureImpure_2] Using PureFunction result twice (2)
LogBlueprintUserMessages: [BP_PureImpure_2] ImpureFunction called
LogBlueprintUserMessages: [BP_PureImpure_2] Using ImpureFunction result twice (1)
LogBlueprintUserMessages: [BP_PureImpure_2] Using ImpureFunction result twice (2)

You’ll notice immediately that the PureFunction was called twice while ImpureFunction was not despite their return values being used the exact same way. The easiest way to explain this is to imagine that impure functions store their results in hidden local variables and using the results will just read whatever value was stored in the hidden variables from the call. Pure functions on the other hand do not store their results in variables automatically. I’m not entirely certain whether this is what actually happens internally but it does explain/describe the behaviour pretty closely. Pure functions are mostly intended for “light weight operations” e.g. simple getters that directly return a variable or contain only very little code. Nested loops or loops over lots of data (such as the 5k tiles) are a bad idea to use together with pure functions unless you cache their result in a (local) variable yourself.

This would not really become a noticable issue with most blueprints or uses of pure functions. However the combination of having a large number of tiles and possibly a large number of returned TilesInRange together with the For Each Loop node that uses the return value from the pure function this becomes a larger problem. The reason for this is how the For Each Loop simply reevaluates its current ArrayIndex against the length of the given Array. For this it also reevaluates the length of the Array each time (since its length may have changed). But because the Array/TilesInRange is not actually cached in a variable, every time the loop condition is checked the pure function is called again to determine the Array. So effectively the number of jumps from the Find All Tiles In Range function multiplies with the number of results returned from it. This can add up pretty quickly in the Runaway counter. Edit: As a rough estimate you can use this calculation for the number of jumps: number of hex tiles * 3 * number of tiles in radius. With number of hex tiles = 5k and number of tiles in radius ~= 100 (for range = 5) we have 1,500,000 jumps already.

As a side note, this is also the reason why one should not assume that pure functions will always return the same result if called multiple times with seamingly the same inputs. If any state has changed that is used by the pure function, the return value may change even if you use the same node and drag another connection from its return value. Because as we have seen in the example above, the pure function will actually be called multiple times.

1 Like