Where to store my "get all actors of class" arrays

Hey guys, here’s my query…

In my project I have my actors track and communicate with each other. To build a “target” list that an individual actor will use I “get all actors of class” at beginplay and store the output in an array variable. During gameplay as actors are destroyed and spawned i remove/add to the array to keep it up to date. So far so good.

Now what ended up happening is that more than one actor class has the same “target” list and I was calling the same “get all actors of class” from several BPs. Even though this only happens on beginplay it still is inefficient. Why store the same set of actors in 2+ separate variables across my project?

**I want to run “get all actors of class” for each of my actors once per level and store their outputs into arrays in a “master_BP” which each actor will be able to access and cast to. **

Considering how common place it is that “this is a slow operation” and “avoid using it every tick”, there is little guidance (as far as I could find) on how to best manage the get all actors of class node.

Right now I am using a UMG widget for this. Is there somewhere better to run this?
I tried doing this in the level blueprint, but I didn’t know you couldn’t cast to it. I tried in a custom GameState, but I couldn’t set it up properly and the game wouldn’t run at all. I tried in an “empty actor” that I place in my level, but I need to set him trough a “get actor of class” node whenever a new actor spawns to be able to cast to him.
With the widget I run a “get all widgets of class” in each actorBP on spawn and cast to it, which to my understanding is cheaper than “get actor of class”.

Some points:

  1. Why do you need this information, what do you use it for?

  2. One empty actor in the level with one array is the best solution ( but I need to know more to check that ).

If it’s only for comunication, why not using event dispatchers?

​​​​​​
A rough scenario would be StaticActor, ActiveActor, PassiveActor, where i have several instances of each ActorBP active at the same time.

Both Active and Passive Actor random roam and look for StaticActor. The way i have them do this is trough a custom pawn sensing. I have Active and passive actor “get all actors of class” StaticActor and store them in an array. A function gets the array of targets (StaticActors) and returns the closest actor. I update the closest target each second (i.e. run the function each second). When they see their closest target each actor moves to it and waits for the other. When ActiveActor waits at StaticActor, his pawn sensing now looks to check if closest PassiveActor is within a set range.(so ActiveActor has an array for all StaticActors and an array for all PassiveActors). If so, PassiveActor is consumed( i.e. destroyed) and ActiveActor goes back to roaming. On destroy PassiveActor removes himself from the array of ActiveActor and when a new one spawns he adds himself ( for this i have passive actor get all actors of class active actor and store them in an array and do for each loop to update all instances).

Tl;dr
StaticActor does nothing
ActiveActor gets all actors of class Static and Passive
PassiveActor gets all actors of class Active and Passive and updates Static array in ActiveActor on destroy and spawn.

Writing ​​​​this out I realize how convoluted it is and it’s projected to get messier. I mean it all works like a charm so far, but it’s getting harder to keep track of who has to update what where. Thus the idea of having a “master_bp” to get and store all actors of class into separate arrays for each class, since actors need to differentiate between them. My Actor_BPs pull whichever array they need and update their own array inside the Master_BP, one for all and all for one kinda communication.

Tell me if you need more context or need me to try and make it clearer.

I’m at work right now, but can post BPs when i get home.

Holy crap, that’s a lot of arrays :slight_smile:

Here’s my take, for what it’s worth.

Technically, static actors only need to read once and could be read by something central. The active and passives could then just copy the array from there ( you can just do it with an assignment ).

But, I think the actives and passives don’t need to keep an eye on each other at all. Why not do it like this:

  1. Central actor reads all statics into array

  2. When active or passive come into being, they copy the array of statics from the center and move towards the nearest one.

  3. When active reaches destination, all it has to do is periodically sphere scan for passives in the vicinity. If it sees one, consume it and then move to the next static.

Right, I need to ask you for clarification on a couple of points, but I’m a bit busy. In the meanwhile can you elaborate on what the “something central” is? Is it an actorBP that I put inside my level and it gets all actors at beginplay?

Yes, exactly that.

So this all sounds like it should work well for my setup. I’ll try to implement it tonight. The questions I have are:

  1. By “sphere scan” you mean sphere trace and look for “hit” output, correct?

  2. How would you check if the hit is an actor from the class you are looking for?

  3. How often can I scan? Is once each second ok for performance? How about 0.5 seconds?

  1. Yup.

  2. Sphere scan has that option

scan.JPG

  1. How often you scan depends on how much you have in the level. If you have, say, < 100 actors of this type, every .25 seconds no problem. If you have thousands, be a bit more careful.

Or, now I think of it, the active actor BP can just contain a collision sphere and wait for overlap. That’s also a possibility.

Thanks, I haven’t used these nodes that often so I don’t know what settings they have. The way I had been doing it so far seemed to work nicely, but your suggestion seems much cheaper and tidier. I’ll see how sphere tracing and collisions would fit in my project with all the BTs and functions I have so far.

Just to follow trough. I ended up storing my arrays on the GameMode since I find it easier to reference to than an actor in my level. I do need to reset the arrays I am storing when starting a new level, so I was thinking of having a new GameMode for each level.

As for setting up my targets:

This is the setup I am currently running for my project.

Some actors need to sense for actors of several classes. If the actor need to keep track of only 1 class, I drop the foreachloop.

This is the function I copied from a youtube tutorial to get the closest target.

I also tried to implement a overlap setup, but it required some fiddling, so I just abandoned it for now.

Ok, sounds good. Overlap can be a bit of a fiddle, a dark art…