For Loops and ticking

I was wondering what happens when a for loop node is executed in blueprint (or in c++ code for that matter) in respect to ticking… Will the For Loop execute the entire loop in one frame? or will it do each loop in its own frame? What exactly dictates that?

I was having trouble using the standard for loop when going through an array because I didn’t want it to go so fast. Everything was happening in one frame, literally a split second. I created a custom For Loop macro, where I manually wire the nodes to execute each loop (i literally loop the wire around to the node for the next iteration of the for-loop body). That didn’t really make a difference. But then I added an extremely small Delay node within the body of executable nodes in my for-loop’s body (tiny fraction of a second). That forces each body of the for loop to be executed in a different frame. (one of the reasons why I had to custom-make my own For-Loop was because I read that Delay within normal For-Loops don’t quite work as expected).

Can anyone shed some insight into all of this? Thanks

Will the For Loop execute the entire
loop in one frame?

Yes - you’re sitting on several GHz of cpu cycles - the processor is more than capable of stepping through an array in under 16 ms (billions of times, too, to be more precise).

You can step through an array at your own pace like so (4 steps a second in this very instance):


Using tick + delay will eventually give you a headache. For all things cyclical and frame independent, do consider giving timers a chance.

2 Likes

Thank you, I have just started to look into Timers because of my question. Although I am not sure that’s what I need exactly. What I want is to go through an array, and make sure each loop is executed in its own frame. So, let’s say I have an array of 1000 entries, I want the for loop to execute over 1000 frames. Is there a way to ensure that?

Or (if I understand you correctly), am I better off using a timer, setting the timer to be the length of a frame (16ms in this case - but that’s for 60fps only how would I make it frame rate independent? delta seconds??) What if I want variable waiting periods…? Checking the looping bool wouldn’t do it for me most likely.

And what about the other part of my question: why does the insertion of a fractional Delay node actually force my loops to execute once per frame? Is this a fluke…?

Can you explain what it is exactly you are trying to accomplish? There may be a better way than looping through an array.

So, let’s say I have an array of 1000
entries, I want the for loop to
execute over 1000 frames. Is there a
way to ensure that?

Sure. You’d need to abandon the for loop macro and use what I suggested above; but instead of the timer increasing the Iterator, have the Tick do it - each frame equals next array element.

Essentially, have each Tick pull the next element from the array - the faster the framerate, the quicker you’ll step through the array.


Is there a specific reason you’d want that? This is precisely what one tries to avoid. Imagine the game running at 30fps, 60fps, 144fps or fps that is fluctuating - now the timing of the loop becomes inconsistent - going through 1000 entries will now take a different length in time.

You generally want to decouple logic from the framerate. You may have a good reason to do what you’re describing, of course. Just asking.

edit:

why does the insertion of a fractional
Delay node actually force my loops to
execute once per frame? Is this a
fluke…?

Hard to say without seeing how the loop runs.

your idea of using an iterator and having a tick pull the next element is probably just what I need… :slight_smile:
but still unclear how to do exactly just that. How does it change your blueprint snapshot above? (manually set a time that equals the frame rate…? how do I get that time value? DeltaSeconds?)

I want to simulate a replication effect, and actions and stuff that gets recorded needs to get replayed at exactly the same sequence and speed, so have to force everything over the same amount of frames. Hope that answers the question…? I’ll see if I can share a BP snapshot of how I’m doing it so far, with an artificially very low/fractional Delay actually achieving what I wanted.

Thanks for your interest buddy. See my response to Everynone down below…

ut still unclear how to do exactly
just that. How does it change your
blueprint snapshot above? (manually
set a time that equals the frame
rate…? how do I get that time value?
DeltaSeconds?)

It’s literally this:

Each tick increases the iterator by 1, use that value to get a specific index from the array. 1 element per frame.

You will want to check the array bounds for this. (in the previous example there was a modulo so the indexes would get wrapped back to the beginning of the array)

Thanks! I’ll try that, though I would have to find a way to avoid literally executing this during all ticks, because I’d only want to run that loop once, or at specific points in time on-demand. Not all the time. I could have a branch to define when it fires, but still that’s an extra check on every tick. Probably fine performance-wise but still, why include a burden like that.
I provide a snapshot of my hacked for-loop. I took the execution of the next loop body out of the standard macro, and you have to wire it specifically from the outside. That way I guarantee that the delay node will fire within the body of the loop. If I remove that delay (or use a normal for each loop), as you rightly pointed out the program just zips through the array and all its effects are squeezed into a fraction of a frame! I saw this hack elsewhere in the forums, have no concrete idea why it works…

I would have to find a way to avoid
literally executing this during all
ticks, because I’d only want to run
that loop once, or at specific points
in time on-demand. Not all the time. I
could have a branch to define when it
fires, but still that’s an extra check
on every tick.

Gate the Tick with a custom event. Open the gate, let it tick the loop, close the gate when you hit the very last index, something along the lines of the following pseudo-script:


The solution with the Delay does seem a wee bit hacky indeed. And unnecessary if the goal is to execute 1 thing per frame. But perhaps I’m missing the bigger picture.

I think a delay works because there’s a code in the background initializing the tick at certain intervals. You aren’t accounting for the fact that each tick is operating on a specific cycle, and not solely your blueprint. I had to do a similar thing in the game Doom (an Unreal Engine game for PS4) in the map editor where setting up a logic chain involved setting a delay in order to ensure that particular events occurred at particular times. That was even with using a timer. In other words, at least some of the code is processing / functioning backwards, as in the code is read backwards by the engine and performed forwards…similar to other aspects of the engine’s processing of graphics and functions. So, in essence, the ticks are almost predisposed to occur at certain points along the frame ‘timeline’, with a number of other factors involved in the compilation and stabilizing of frame rate. How you are trying to do a sequence of repeating actions / functions is not practical, and is probably going to end up not with the results you intend, while also becoming really difficult to debug when it encounters issues. If you had a deeper level understanding of the tick and how it works with frames, you’d have a better chance at succeeding in it. But so far, it looks disappointingly like it’s going to result in failure and wasted time and effort. Do at least a bit of reading about frame rate and tick time, and how those correspond and connect functionally (not in the code). I did a bit of reading yesterday, and recalled your post about trying to sync tick-based timing of events with each frame in a composite sequence, and was immediately stifled by the prospect of attempting it because of the details I read. It’s already difficult enough for video card makers to ensure smooth, stable frame rate. How do you propose resolving that in a simpler blueprints network? I suggest discovering a different way to perform the intended objective.

Above a certain amount of executions the engine will stop the simulation and throw an error about an infinite loop. You can try it in blueprint by using a for loop and
setting a massive number to last index.

Unless that error happens, it should be safe to assume that the whole loop executed itself properly.

In project settings you have maximum loop iteration count setting which you can adjust, but I’d only advice doing so if you know what you’re doing it for.

If you package the project and have an infinite loop in a game, the engine will terminate the loop at some point and otherwise continue the game.
Or at least it used to, but I tested this many many versions ago, so that behaviour might have changed.

I’m not perfectly educated on the subject but afaik the big cost with BP vs C++ is that in BP, the performance cost of the wires running between nodes
is rather high, so if you have a lot of wires the execution cost can add up, especially with loops. The performance can be improved by implementing the
loop or some of its logic in C++ instead.

Hmmm… I am not sure I caught everything you said there, but basically what I am trying to achieve is make sure that each action in my for loop is executed on its own frame. I actually don’t care too much about what time or sequence within that frame. If that makes sense. I specifically want to refresh a pawn’s location and rotation and certain actions that are triggered by simple key presses or booleans. So I only care about things get updated by the end of each frame. Not inserting a tiny delay within the for loop, as Everynone correctly pointed out, the engine was making easy (super easy) work of going through my array of actions (in the hundreds or maybe low thousands in number) in a split second. Rather than a more realistic time frame that these instructions were recorded at. If perhaps i’m following correctly, you’re saying that maybe this tiny delay may compound and may cause things to happen outside the tick/frame they’re supposed to? Perhaps. That’s why I tried to specify a really tiny delay in seconds. But also thinking of implementing a tick approach as suggested by Everynone and just force each item in the array be handled in its own tick/frame for sure.

Wow, super cool! I’ll try that approach. Thanks so much!!

Follow-up: as I’m trying to optimize for speed (maybe not hugely important now as I’m prototyping but definitely useful for later), any idea of how to implement the Gate + For Loop approach in C++ code instead?

Very insightful, thank you. I’m actually in the middle/second category. The actual meat of the algorithm, i.e. where actions get executed, is in C++, called by a node in the BP. The for-loop macro was used in BP because when I tried to do it in C++, as I was trying to explain earlier to Everynone, the for loop was going way too fast for me, completing in a single frame (even if it was more than one, certainly 10s or 100s of times faster than it needed to be). I couldn’t figure out how to insert a simple Delay in C++ code, and the TimerHandle approach was a bit too complicated for me. I tried that too, but it didn’t work for me, most likely because I probably didn’t implement it so well. I’m prototyping so went for the path of least resistance.

Well, I wasn’t entirely clear about what the objective is in your approach of fitting each update (pawn’s location, rotation, and certain actions) into each frame before frame ends. I’m still not. That’s probably why I’m not coming across clearly to you with what I said. It is probable that the update could be pushed beyond its reference frame, on a per frame basis, or merely for certain frames. That is what I was getting at somewhat with the reading I did, and how ticks work. There’s something before the tick occurs that happens in a time-related basis, and sounds as though it’s independent of frame rate…and it simply appeared that it would most likely cause an extra portion of time to be added to the frame when updating per tick or frame. What is the effect you’re intending to create? Lots of things are updated per tick already, and within frames, so how is what you’re trying for different?

I’ve explicitly now linked the execution of my loop with the tick event so I think it works even (slightly) better than ever before.
What I’m basically trying to do is have another pawn mimic the player’s pawn after a continuous stream of actions and movements are recorded. I wanted the effect to be realistic, so each series of actions and movements performed have to be re-enacted. I can’t have movement and rotations happen too fast in a frame etc. So I capture information every frame and then have to replay it exactly as it happened.
Hope that provides some clarity. I tried recording stuff with real seconds, and trying to space it out based on that time, but it was too complicated. A version of it initially did work ok but not when I keep adding on actions that can be recorded and replayed. At the end of the day all I care about is whatever happened and can be recorded in one frame can be replayed back back one frame at a time.

Update: @Everynone
I implemented your approach and it works well. Just wanted to say thanks again. If you have any advice on how to to approach this in C++ for optimal performance that’d also be great. Otherwise I think this works just as well (perhaps even slightly better than - though not sure yet) the earlier approach with the “hacky” Delay node.

I haven’t done anything in code for years now, last time before UE4 was released. Can’t help here, not without investing a considerate amount of time into untangling the UE4’s side of things. Which I know I should do anyway :expressionless:

While it is quite true that the BPs are generally much slower than the native code (to the point where a large loop may fail to execute), consider looking into nativisation - the results are pretty good.