Get All Actors Of Class not working with Decal Actor

I am trying to delete all decals in the level via a For Each Loop. I’m using the “Get All Actors Of Class” to attempt to find all decals but it doesn’t work - the debug log prints that it looped 0 times meaning it didn’t find anything. Here’s my level blueprint:

Note that no decals are initially created when the map loads, but the decals are being created via “Spawn Decal at Location” when an actor is destroyed, like so:

This method works great when deleting objects of a different class than “Decal Actor”, but not with decals that have been spawned at a location. Could someone please help me get this working?

I haven’t worked with decals much but looking at the return type, it seems that a decal is not an actor but a component. Try it like this and see if that helps:

224236-capture.png

Hey there, Spawn Decals doesn’t create a DecalActor, but instead creates a Decal Component. Since you are using Spawn Decal At Location then that means that he adds the decal component to the World Settings actor that is inside the GetWorld(). The problem is that i don’t think you can access that in Blueprints, you would need to create a get function in c++ that would do that for you, something like:

TArray<UDecalComponent *> AYourActor::GetDecalComponents()
{
    TArray<UDecalComponent *> DecalComponents;

     if(GetWorld() != nullptr && GetWorld()->GetWorldSettings() != nullptr)
     {
         TArray<UActorComponent *> ActorComponents = GetWorld()->GetWorldSettings()->GetComponentsByClass(UDecalComponent::StaticClass());

         for(UActorComponent * ActorComponent : ActorComponents)
         {
              UDecalComponent * DecalComponent = Cast<UDecalComponent>(ActorComponent);

              DecalComponents.Add(DecalComponent);
         }
     }

     return DecalComponents;
}

If you want to do the decal array construction in blueprints then just do this:

AWorldSettings * AYourActor::GetWorldSettings()
{
     if(GetWorld() == nullptr)
         return nullptr;

     return GetWorld()->GetWorldSettings();
}

And in blueprints do GetComponentsByClass node and foreach ActorComponent just cast it to DecalComponent and do whatever you want to do.

I think i’ve found a way. If you do a Get All Actors of Class with World Settings it should work.

Surething, dont forget that you still need to do Get Components by Class of UDecalComponent from the World Settings actor.

Oh, wow! Well thank you for the help - I appreciate it but I am a beginner so unfortunately I don’t have any C++ experience yet. Maybe I can try to stumble my way through the C++…

I can’t accomplish what I’m trying to do purely with blueprints though?

If not, is there a way to spawn a decal differently so it is exposed to BP?

Unfortunately this does not work. Probably due to the reason that xlar8or said. :frowning:

I’ll give this a shot tonight and see if I can get it working!

Here you go, i just get the first World Settings actor if its valid and then get all the decalcomponents attached to it.

If it’s not too much trouble would you mind taking a quick blueprint screenshot?

This works great! Thank you so much! :slight_smile:

You are welcome :slight_smile:

Have they changed this? This no longer works

It’s working fine for me:

Are you on 5.4?
It finds world settings and decal component, but when I destroy actor it does nothing and decals are still there.

Yes, I’m on 5.4. Don’t you mean destroy the component, and not the actor? Can you show me your code?

Ah yes, component, my bad.

EDIT: Oh it actually removes ONE decal every time I run it… not sure how to get it to remove all…

EDIT2: So if I spawn in 2 decals, I have to run it twice to get rid of both of them, if I spawn in 10 decals I have to run it 4 times for all of them to disappear… something really strange going on

I’m assuming you are executing that code at runtime. Can you also put a print after the Destroy Component to make sure it’s being executed?

As a side note: You don’t need that branch, because if the array is empty the For Each Loop will leave immediately.

it is executing, I get print messages, I spawned in loads of decals and first run it removes maybe 30 of them, and then it seems to pretty much half every time I run it until they’re all gone.
Also removed the valid branch.
I use spawn decal at location to spawn them in, could that be causing this? Is there even another way to spawn them in?

Edit: Added a counter and yes it is removing exactly half of them each time I execute it …??

Edit2: I think I figured out why this is happening…
When I delete a decal the decal above it in the array gets moved down to the deleted position and then the For loop counts up and moves on to the second decal, which used to be the third…
I have no idea if this is how it works, but this is the only way I can make sense of why this is happening. I will try to put all decal components into an array first and then delete them when i have time.

You should use a Reverse For Each loop for these cases where the array is being changed while looping, that way you remove from the end and work your way to the beginning without needing to duplicate the array.