i got a fairly large function (doing the building logic of a maze). This works well to the point where i raise the max rounds the builder must do (for a larger maze). Due to the random buildup, sometimes the function succeeds (building beautiful mazes), but the greater MaxRounds is set, chances raises the code fails with the infinite loop message. While this is basically understood, and can be prevented by raising the max loop value in the project settings, from 1Mio to 10Mio, it stills feels somewhat hacky and instable. In addition, we are in a early stage of the project, and lots of additional code and functionality still has to be added…
So, the question about basic logic behind looping in function arises. To be a bit more specific: While i do indeed have several stages of nesting inside that function, and some of them can build up to lets say 200 items to loop, most of the loops stay under 20 turns. In addition, there is absolutely no while-loop. Its all just ForEach-loops, some with break. There is currently no chance any of these loops can even reach 1000…
That leads me to the supposition, loop counting/indexing in nested loops (inside one function) is somewhat counted togehter. To be more specific, it must be multiplying, since with addition, we never would reach that number of 1Mio counts.
Can somebody shed some light on this nested loop, infinite loop triggering thing? Am i (completely) wrong with my guess? Is there any other explanation, what causes the infinite loop failure where no individual loop even reaches 1000?
However, i’m fully aware i will have to rewrite that thing, making several portions to be calculated seperately, as far as possible…
Suppose you have two nested loops (one outer loop and one inner loop). If both loops iterate 1000 times each, that’s 1 million total iterations. If you have three nested loops, that’s a billion iterations. I’m not sure I understand the way you’re describing how you add up the iterations.
In any case, there are many ways to trigger the infinite loop warning, not just loop count. If an inner loop state doesn’t change, you can trigger it. That would be impossible to do with a for each loop unless you’re modifying the array or container itself.
Another way to get the warning is if you Destroy the actor the blueprint is running in. You have to destroy it the next tick. There’s a node for this. DelayNextTick or something.
And lastly, if the blueprint just takes too long to run and stops the game from processing frames in a timely manner, it will trigger the warning.
Hi @AlienRenders
Thanks for your helpful input.
I’m afraid i have to come back to this iteration counting thing and how it is treated in UE. Let’s stay with your example for now: If the outer ForEach runs 1000 times, and the inner also, its for sure 1Mio iterations for the innermost code portion, but both loop counters itself never exceed 1000. So, there must be some internal instance, multiplying things on runtime (number of loops is not known to the code before effectively getting an array into a ForEach). This is the core of the somewhat theoretical question.
Considering your list of possible infinite loop triggers, just in case i missed someting out here:
First: It was made sure, only ForEach is used, no while loops or other manual looping without breakout condition. There is one Loop where the employed array eventually is altered, but the only option is remove one element, and “no more element is left” is catched.
Second: There is no actor to destroy, as the function runs in an custom uobject. But i will now be aware of this just in case. Thanks for that.
And the last one: Even if there is an internal multiplier for nested loops, there surely must be some timeout conditon to stop nested loop structures from running infinitely (since every single counter inside that nested structure can easily stay small). This one would be somewhat fuzzy and hard to catch.
But anyway, especially if its the last case i encounter here. There is no way around cutting things apart and doing some smaller code portions…
I think the iteration counts are counted per tick. I don’t know for sure, but everything I’ve seen for the infinite loop warning has been per tick.
Anyhow, that’s why I put long processing tasks in C++. I’ve seen people say that the Construction script isn’t limited by timeout restrictions and even the count limitation (though I can’t be sure if any of this is true or not). So you could perhaps try that. Just spawn an actor that creates the maze and put your graph in the construction script. Easy enough to do and minimal changes. Again, make sure to destroy the actor on the next tick (or later).
Note that for you to use the Construction script, you MUST spawn the actor. In a standalone game, if the actor is already in the level, it will NOT execute the Construction script.
i will gratefully keep your tips and recommendations in mind. For now, the code runs as it is, and anyway has to evolve in various aspects. There is also a lot to be done regarding efficency…