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?
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.
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!
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.
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
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.
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.
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!
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.
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!
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.
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!
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.
I made this system that compares the distance between the “self” and the actor with an arbitrarily large number. Then set the closest distance as the one to follow.
But the problem is that whatever system I try to make, my “seeker” units follow a cluster pattern of specific actors regardless of distance, as displayed here.
What’s happening here is the units in the front, even by a little, tiny bit, are indeed registering as the closest enemy. What happens when the armies collide?
Provided, that’s what I think I’m seeing. Are the line traces starting on the North side of the image and tracing to the South? That’s what I’m getting from this. I’m not sure what the spheres are. Could you maybe explain the image?
Well, the circles are just tracing circles. They designate the closest actor that the opposite “seeker” actors found.
The “northern” actors in this screenshot are the ones that seek the closest actor, the southern actors are those that are being sought.
So, I don’t think that they find the closest actor but for some reason can seek only specific actors from the unit while ignoring the rest, hence the clustering of tracing lines.
Can you explain then, why these poor buds get line traces but no spheres? That could be a thread to unravel to help figure out why this is happening:
It really does seem like these lines are gravitating towards the actors that are indeed the closest, but the difference is by tiny amounts of distance. Maybe try staggering them, with exact distances as testing? These seem very naturally placed, maybe set it up like a “Power Pawns” setup in chess, but with every actor on a multiple of 50 on the X and Y for more accurate testing results? Even one being placed .0001 further forward on the X could make an entire group all focus that one.
Hope that gets your creative logic juices flowing with ideas!