Get all actors of class vs Get all actors with tag

Which one is faster in blueprint : Get all actors of class OR Get all actors with tag ?
I am working on a mobile game and this is very important

If there’s a lot of actors and speed is important, then don’t use either. Use event dispatchers.

If the number of actors in < 20, say, it doesn’t matter.

Researched this a long time ago here is the post:
https://www.casualdistractiongames.c…tallactorswith

tldr - Internally, on each class, UE4 maintains a hashmap of all instances of it.

afaik GetAllActorsFromClass should be orders of magnitude faster than GetAllActorsWithInterface and GetAllActorsWithTag, since it utilizes that class specific HashMap. (Deep class hierarchies still require traversing)

Disclaimer: I haven’t looked into this for a long while - so things may have changed. It’s worth digging in to the source if you are curious as there are several interesting things to discover…If you do, please be sure to post any additional findings…

3 Likes

Just to clarify - if you have 1000 actors in your level, and 5 of them are of Class FOO and also tagged FOO:
For GetAllActorsFromClass , TActorIterator should be traversing a HashMap of 5 where GetAllActorsWithTag is traversing the full 1000.

Just ran a quick test:
In a scene with 40000 actors in it:

GetAllActorsWithTag takes about .0039 seconds
GetAllActorsFromClass
**.000011

BTW Looks like there is also a GetAllActorsOfClassWithTag node now too… sweet.**

10 Likes

What about the hard referencing? Say you have 1000 actors that need to be saved before the level unloads, and they all need to bind to a certain blueprint that calls the “onSaving” ED, for them to pass their data to the GI, for example.
All of them have to hard reference that one blueprint. Isn’t that blueprint being replicated in memory 1000 times at that point?

If the 1000 are all the same type of actor, it only gets loaded into memory once.

Not if you use a dispatcher, that’s the point I was making :slight_smile:

How? You mean the same class? Is there any documentation on this?

Well, you have to have a hard reference to bind to, right?

If you have a level with 5000 of the same class in it, that class only gets loaded once for the level.

All this business with soft/hard references, is to stop the engine loading thing you aren’t going to use.

If you’ve got 5000 in the level, well, er, you are using it.

1 Like

Yes… but all 1000 actors bind to ONE dispatcher.

Got it, they bind to one dispatcher, obviously. But each still needs to reference the caller, right? Like you said, 5000 times.

1 Like

Yes, but that’s fairly trivial, it’s not going to be eating memory like, textures, for instance.

1 Like

Any official documentation on this? How much memory exactly, what?

I assume there’s no docs, because if you’re really that bothered about how a dispatcher is setup, you can just look in the engine code ( no, I have not looked ).

But I can tell you, it’s a handful of bytes for each actor. So even if you have 1000s of binding actors, it’s still nowhere as bad as even ONE texture :slight_smile:

1 Like

Does Get All Actors With Tag create a hard reference in runtime? I assumed this because it has to search for all the actors with a tag and then load this into memory. Or am I mistaken?

It depends what you do with the actors you get back.

If you make an interface call on them, there’s no hard refs, but if you cast them, you have hard refs at runtime and in editor.

1 Like

(post deleted by author)

Thank you so much for getting back to me on this because I’ve been really confused about the whole thing. I was told that even things associated with Interfaces like: Get All Actors With Interface, or Get All Widgets With Interface, or With tag like I have in my example, would be exactly the same as using a Get All Actors Of Class because the memory load has to do with Unreal needing to search for all of those actors and then store them until they are used.

This is what I was concerned about because if you have like 90 actors in your game and then stored in an array, isn’t searching for all of those actors with an interface technically still loading all 90 whether you are using them or not? And then at what point are they being unloaded after use or not being used? I had trouble believing what I was told because I felt it would defeat the entire purpose of even using interfaces if they create hard refs just like casting does.

I’m really trying to understand at what point does this become taxing on the memory. Can you give me a more detailed explanation?

As you can see in my set-up here, I had the nodes placed to where after the message is sent to the actor with the tag, the array with the stored actors then clears to free up memory. Or at least I hoped that it would work that way. But is something like that even necessary? And is it even being used correctly?

I prefer to use get all actors or widgets with interface, but I want to be sure about it. It’s always so tricky because we cannot really see what is being loaded into memory during runtime.

If I’m not mistaken:

  • Get All Actor of Class only iterates over a hash of all actors of the given class that are part of the world. Just like @OptimisticMonkey says above.
  • Get All Actor With Interface iterates over every actor in the world and checks if (Actor->GetClass()->ImplementsInterface(Interface)).
  • Get All Actor With Tag is the same as with interface but checks if (Actor->ActorHasTag(Tag)).

I can’t find the post, but I remember some time ago @Chatouille tested and concluded the return array was treated as weak pointers, meaning they don’t keep any actor from getting GCed. Only one of the node was tested, though.


So if I’m not mistaken:

They are not the same. All are fairly expensive compared to Get All Actors Of Class.

Nothing is loaded with these nodes. What is returned is a copy of the memory address of the instances in the world.

They are treated a TWeakPtr<> meaning it will not prevent destruction of the referenced objects. (I’ll update if I can find the post)

In the image the only memory you are freeing is the actor instance at index 0 when destroyed and the allocated space of the array,an array thats not really necesarry in this particular case. That would be the 64-bit size reference per index + some overhead for the array.


Hope this makes sense.

Anyone is more than welcome to correct or add anything. :pray:

3 Likes