I am generating an infinite obstacle course. The way it works currently, is it generates 1 part of the course, which in it has 2 triggers. When one trigger is touched, it spawns another part of the course right below the previous one. The other trigger is a destroy trigger, that when overlapped, destroy the self actor (thus clearing previously generated parts of the course).
On begin play each course spawns obstacle actors. Now to destroy these obstacle actors, when generating, I attach them to the part of the course. And before destroying the course itself, I do “Get Attached Actors”, and destroy them in a for each loop.
The problem is, 1 attached actor always remains not destroyed for some reason.
I tried printing string for each element, and it does print all the 3 strings, but destroys only 2 for some reason. Why?
It prints “Generated” 3 times. But prints “Destroyed” Only twice, and destroys only 2 actors instead of 3.
But if I try to print array index before destroying, it prints 3 times.
P.S. On the hierarchy also I can see clearly that the 3 obstacle actors are parented to the course part actor. When destroying the course and 2 actors disappear from the hierarchy, but one actor just gets unparented and doesn’t destroy
I did solve this by adding generated actors to an array, and then looping through that array to destroy, instead of looping through “Get Attached Actors”.
But since I’m just learning Unreal, I want to know why the issue occurred in the first place, since it doesn’t make sense.
The way BP Graphs work, every time an Exec node is evaluated, its input pins are re-evaluated. In case of ForEachLoop you can assume the Array input pin is re-evaluated before each LoopBody execution (and before Completed as well).
Since the input pin is a pure function call (Self->GetAttachedActors), it is also re-evaluated.
And since you are destroying actor in LoopBody, the result of GetAttachedActors has one less element with every loop check, resulting in skipping every other element. First iteration index=0 you remove first element, then index=1 but GetAttachedActors only returns 2 elements now, you remove the second element (which is the third actor), then index=2 and you are out of bounds so the loop completes. The second actor is never removed.
Promoting to variable is generally the right solution to avoid this.
Sometimes it is not needed, if you are using the result of an Exec node instead of a pure node (no exec pin). For example the result of “Get All Actors Of Class” node. Exec nodes are not re-evaluated unless you trigger their input exec flow. Their output pins behave like global graph variables.