Get overlapping actors not getting all the actors in a box despite them being identical (UE4.27)

i’m trying to remove grass that overlap actors with a simple sphere to act as the bounds for removing.

as you can see there’s still 4 pieces of grass left

Are you sure that all the grass object come from the same class parent ?

You’re looking to find “Grass 01” classes, but can the left grasses be “Grass 02” or another grass type ?

If every grass object have the same parent class it should work, at least if every child class has “Generate Overlap Events” checked

i have fixed it by using reverse for each loop instead of for each loop. not sure how it fixs it but it does.

1 Like

While I’m not sure this applies to this specific Blueprint – I’d need to go dig into how the Blueprint stuff is implemented under the hood – in many languages there can indeed be situations where you do want to reverse the loop for something like this.

For instance, say you have a validating array class that will remove any invalid item from it. (Such as an actor that’s no longer around.) If you iterated forward, it would be like:

  1. Get first item (position 0 in array).
  2. Destroy the item.
  3. Because array validates, the first item is removed and everything shifts down a space. Item at position 1 is now at 0, etc.
  4. Get second item (position 1 in array).
  5. Since everything shifted down one, you’re now missing the actual second item (which is now in position 0).
  6. Destroy the item you got.
  7. Because array validates, everything shifts down a space.
  8. Get the item at position 2.
  9. Since everything shifted down, you have items at position 0 and position 1 which you’re skipping.
  10. Etc.

Whereas if you iterate in reverse order, you get the last item… and the array doesn’t rearrange when it’s destroyed. Then you get the next-to-last item, and so on. So you actually do go through the whole array.

While I do not know offhand whether this is true for Blueprint or not – thus whether it’s the root cause for you – this is why I’ll generally do a destructive operation (like what you’re doing here) in reverse order, just in case there’s an implementation detail under the hood about how it’s iterating that I’m not aware of.

2 Likes

Unfortunately that solution does not work when working with C++ and calling something like OverlapMultiByObjectType(). Hoping someone can provide more insight into this.

1 Like

You are exactly right.

Strange thing is i had the same problem today with looping through an get overlapping actors array. But I did not destroy the actors in the loop I called a function on these actors … And still the reverse loop got all actors the normal loop only got some actors. Very strange but your solution helped!. Thx

This not really a good solution. You need to understand pure nodes:
“Get Overlapping Actors” is a pure node (no execution pins), every pure node will be called every time it is accessed, in this case every loop!. So in this example, let’s say there are 4 Actors in the sphere, if you run the code with a normal loop, the following happens:

    1. Loop Call → Get Overlapping Actors → Found 4 Actors → Actors[0] → Destroy (works)
    1. Loop Call → Get Overlapping Actors → Found 3 Actors → Actors[1] → Destroy (works, but the first one was skipped)
    1. Loop Call → Get Overlapping Actors → Found 2 Actors → Actors[2] → Destroy (does NOT work, since index 2 is not valid anymore)
    1. Loop Call → Get Overlapping Actors → Found 1 Actors → Actors[3] → Destroy (does NOT work, since index 3 is not valid anymore)

if you run the code with a reverse loop, the following happens:

    1. Loop Call → Get Overlapping Actors → Found 4 Actors → Actors[3] → Destroy (works)
    1. Loop Call → Get Overlapping Actors → Found 3 Actors → Actors[2] → Destroy (works)
    1. Loop Call → Get Overlapping Actors → Found 2 Actors → Actors[1] → Destroy (works)
    1. Loop Call → Get Overlapping Actors → Found 1 Actors → Actors[0] → Destroy (works)

The better solution is very simple, save the result from “Get Overlapping Actors” to a variable and loop the variable. The “Get Overlapping Actors” will be run only once now (to set the variable) and the array in the varialbe will not be changed when you destroy actors.

So this code will run like this:

  • Get Overlapping Actors → Found 4 Actors → save as “Actors”
    1. Loop Call → Actors[0] → Destroy
    1. Loop Call → Actors[1] → Destroy
    1. Loop Call → Actors[2] → Destroy
    1. Loop Call → Actors[3] → Destroy