Why does Load Stream level break my foreach loop?

I’m trying to cycle through every sublevel in my game, load it for a split second, then unload it and move on to the next. The best way I’ve come up with to accomplish this is to curate a TArray of every level name in my game, and iterate through it at runtime:

This seems perfectly straightforward (if a little hacky), but I’ve run into a problem I can’t get my head around: every time this runs, it only executes the Load Stream Level node for the first level name in the array. I’ve verified that each level name is spelled correctly, and changing the order of the array changes which level gets loaded, but after the first sublevel is streamed in the loop always terminates. Is there something obvious I’m doing wrong here?

It’s not probably breaking, to verify this you could put a print after the load stream level node, to see if it’s actually breaking the loop. What I think it’s happening is this:

If you check the link to the unreal documentation for this node: https://docs.unrealengine.com/latest/INT/BlueprintAPI/Game/LoadStreamLevel/index.html

It says:

Stream the level with the LevelName ; Calling again before it finishes has no effect

So maybe that’s the problem, the loop is going too fast and the node doesn’t get enough time to finish.

That’s interesting, I hadn’t caught the fact that it won’t fire if it’s already firing… I am pretty sure the loop doesn’t progress though, I added a print statement that fires after each iteration and displays its index, and it verifies that the logic after the foreach node only executes once, regardless of the size of the array. I also tested to see if the load stream level nodes were interfering with each other by replacing the loop with a hardcoded call to each level, and this version correctly loads and initializes everything:

I suppose it’s possible that the system just never intended you to use the load stream node with an iterator, it’s a slightly strange way to initialize all the sublevels.

This is still a problem with Unreal. UE 4.25.1

Its infuriating. Why does this not work? Its ridiculous.

For anyone coming across this post.

The reason why the node does not work in a (standard) For-Loop is due to how Latent Actions get registered.
When a “Load Stream Level” node is executed, the Engine checks the Latent Action Manager for an already running Latent Action with the provided parameters (ID and Callback Target) and only proceeds when no such exists.

However, it does not check if the new action differs by custom parameters (such as LevelName) compared to the previous call - hence, the first item gets queued, while the second call gets rejected on account of the two Actions being identified as identical based on the scope of comparison.

It’s the same reason why a Delay node called multiple times before it finishes (e.g. in a tick), won’t execute multiple times and will not update the delay time (a retriggerable delay will however as it specifically accounts for the above).

Here are two examples for workarounds to this problem:

  1. Instead of the “Load Stream Level” node, one can access members of a Streaming Level directly, i.e. bShouldBeLoaded, bShouldBeVisible, bShouldBlockOnLoad, and events such as OnLevelLoaded (all sublevels added to your persistent level will have a valid instance on game start, even if not loaded): Streaming Levels from a For Loop posted by anonymous | blueprintUE | PasteBin For Unreal Engine 4

  2. The Load Streaming Level node can still be used, but only with a modified For-Loop macro that has an external iterator: LoadStreamLevel from custom Loop posted by anonymous | blueprintUE | PasteBin For Unreal Engine 4

Custom latent-friendly For-Each-Loop macro: Custom latent friendly for-loop macro posted by anonymous | blueprintUE | PasteBin For Unreal Engine 4

In the first example, all levels will be queued simultaneously, while the second example enforces a sequential load order (Note: “Block On Load” parameter is not relevant here, synchronous and asynchronous loading methods will work in both examples. The next level will just be queued when the previous finished loading and the Completed pin fires).

4 Likes

Perfect explanation and great links! There’s also a great thread with various solutions to hack ForEachLoop for latent actions here > https://answers.unrealengine.com/questions/50642/question-how-do-i-add-a-delay-to-each-iteration-of.html

But yeah, I agree that it’s unintuitive the way ForEachLoop works in situations like this, but once you understand the macro it really makes perfect sense why it doesn’t. The frustrating part at this point is that there’s not an official macro included from Epic.

This is gospel, thanks

thank you. your answer save me and my time!