How to make an AI actor follow multiple copies of an actor class

As the title suggests, I have made a behaviour tree with an AI actor that does not follow the player but an actor of class

Everything works fine when the AI actor has to follow a single copy of that actor.
The problem is that I spawn many copies of the same actor on the map but the AI actor only chooses one out of the many to follow, totally ignoring the rest.

How do I make the AI to follow every instance-copy of that actor class on the map, let’s as the closest one?

Hey @Napoleontas1769!

The problem here is you’re querying the environment for only one of these objects.
What you need to look for is “Get All Actors of Class” and save that as a variable. Don’t do this every time you want to seek, as it’s very resource-heavy, so saving the array will work.

Something like this would work better.

This gathers all actors of that class, and then sets the first one in the list as the closest. Then, it cycles through all of them, and compares them to the current “Known Closest” in the array. Once they’ve all been run through and the final closest object is determined, it will set that as the object on your blackboard.

Let us know if there’s anything I can clarify further!

1 Like

Thank you very much for replying with an example.

Unfortunately, though, it doesn’t work as expected.

The AI still follows one of the identical actors on my test map.

Here is a visual example of what I’m talking about.

Hi,
From the looks of it what Mind Brain suggested should be working.
Could you share some screenshots of you blueprints? Perhaps also a video of the issue and of a debug of the behavior tree. This would make helping you easier.

So I have a behaviour tree with a “move to target” task and a blackboard key set as an object=actor

On the Ai controller, I run the code provided by Mind-Brain

The only thing that I’ve found is that when I un-check the “instance-synced” on my blackboard “AttackTarget” key, the Ai will occasionally move to a different instance-copy of the character that is supposed to follow, but it won’t do it dynamically. It won’t change targets according to distance at all.

So from what I can see it seems like you only select the actor to track in the beginPlay but then it doesn’t check if the closest target has change.

The blueprint script given by Mind Brain should also be called inside your behavior tree. I didn’t work on AI since a while back but I think making a Service is the way to update data periodically. Behavior Tree User Guide | Unreal Engine 4.26 Documentation

Thanks for the reply!

I haven’t used services before, so I’m unsure how to implement it. Having watched a few tutorials I might have an idea or two.

I was also thinking about the “On pawn sense” node but I know that it is expensive to use especially on hundreds of npcs.

A simpler to test things would be to redo you distance check every now and then inside your AI tick, which you can slow don inside your class settings. So you can ask your AI to tick only once every second and check if the closest enemy has changed.
The point of a service is to make sure that calculation are only performed if the AI is actually following someone, as updating the target isn’t useful if the AI is doing something unrelated. But to test if things work that would be good first step to do it inside a slow tick, or with a timer.

I tested the exact same line of code on the “On pawn sense” node just for testing purposes.

The Ai just flip-flops between the two copies of the character it is supposed to follow, ignoring the distance.

Hey @Napoleontas1769! Sorry for the late reply, I was out for the weekend.

On Pawn Sensed is a problematic node for this idea, as it will fire CONSTANTLY as long as there is any pawn within range, and the “Get All Actors Of Class” node is very heavy. You will likely experience glitches with the array doing this.

Instead, you could do the GET ALL on Begin play, then with On Pawn Sensed array you could use a “Contains Item” node. Then plug the sensed pawn into there along with the Actor Array, and using that node gives you a bool. Grab that and make a branch - on True, do nothing because it is in the array, on False, add it to the array. Then every second or so (try using a timer) run the “Which is closest” bit, and use a service on the BT checking for updates to that variable.

Thank you very much for the reply!

Unfortunately, there are some things that I don’t understand clearly.

1)So, I should run this code in the AI controller or as a task?
2) I don’t really understand which is the “on pawn sensed array”, the array in the get all actors?
3) How would I use Event begin together with “on pawn”? Should I combine them inside the AIC?

I’m a bit at a loss with the explanation, probably because I’m not that experienced in building AI.
In fact it is the first time I have attempted something like that.

Okay, after some thought I realized “Why not use a timer?”

The first time it sees a target it’s going to run “On Perception Updated.” Which will run this code, forget using BeginPlay and GetAllActors. You don’t want it to do that because what if it’s not supposed to see anyone yet, like if it’s behind walls. “OnPerceptionUpdated” will limit setting it to only times that it perceives targets.

Running this timer at the end will make it re-evaluate every time it completes. Here I have it set to every second, you can set it to however often you’d like. I also added a check to see if the Perception is updated to having 0 items in it, to then stop the looping timer and reset it. I also spread it out a bit to make it more readable.
I didn’t have time to fully test it, so once you implement it let me know if there’s any wonky stuff! :slight_smile:

Edit: Depending on how many things you have it set to perceive, you may need a “Filter Array” node before the ForEach Loop to make sure the elements are what you want.

1 Like

Thanks!
I’ll try to test this as thoroughly as I can and let you know about the results.

In the meantime, I’ll also try to understand the logic behind it because there are some nodes that I’ve never seen before here.

1 Like

If you have any questions, please don’t be afraid to ask! I could explain the whole thing piece-by-piece but it might read like a legal document, so ask about any parts you don’t understand and I’ll be glad to explain. This is a combination of some very useful systems that can be used on nearly all blueprints, so knowing these will be really helpful to you! :slight_smile:

1 Like

Your continuous help is very much appreciated!

This is what I’m doing but inside the AI controller. I’m also running a behaviour tree on posses.

There is a slight difference in the behaviour of the Ai . They do occasionally pick the second instance of the character, but once moved they just follow the one they picked.
It isn’t dynamically changing its target according to distance.

I’m guessing here that the “updated actors” output on the On perception node is using any actors that are being sensed by the Aicontroller, since I haven’t manually defined the variable, it just existed by default.

EDIT: After testing it, the AI follows the LAST actor instance that moved, regardless of proximity.

Okay! I THINK this narrows it down enough to really finish it out!

Here’s the overall:

And here are most of the changed things so you can read more clearly.

We’re getting rid of “OnPerceptionUpdated”. This does get rid of the reset of the timer, because we want it to keep looping until deletion of the actor or other stop reasons. But only going once per second makes this 1/60th of the load that would happen if it were put on “EventTick”.

So this will start on possession of the pawn, and then run every 1.0 second after, and instead of the updated targets (which is only things that have changed) it’s getting everything currently perceived by the AI, then finding the closest! :slight_smile:

Also we keep the “>0” branch to preserve a little resources if there is nothing perceived, it hits the “False” and waits the 1.0s to try again.

1 Like