Why does Load Stream level break my foreach loop?

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