Building super-simple crowd AI with BPs?

I’m currently messing around with , and I’m not sure what the best approach is; I’m wondering if anyone can offer some insight.

My default enemy character attacks by melee; his AI instructions are a simple “Move To Actor”, followed by an attack. The problem is, if there are many enemies on screen, like 30-40, they all tend to clump into a knot trying to reach the player.

By enabling RVO Avoidance, I can partially solve problem; the first wave of enemies nicely fan out in a circle around the player, each within attacking distance, and rest.

The problem comes with the second wave of enemies; since there is no valid way for these enemies to reach the player, they sort of gently shove their way around the first ring of enemies permanently, and never “sleep” where they’re standing.

My instinct was to mess with stuff like “does path exist” to check for circumstances like … But RVO is path agnostic, and the presence of other enemies doesn’t actually communicate " path is obstructed" to other enemies, so they don’t understand that the player is unreachable.

I also considered using some sort of timer check; i.e. If you are attempting to reach the player and it doesn’t work, simply idle. The problem with is, if the player is simply running around in a way that prevents enemies from ever getting to the player, they’ll eventually give up the chase (determining it to be “impossible”) and just stand around; obviously is not desired.

I tried more complex stuff (i.e. a BT Service that performs a simple sphere overlap check for other nearby enemies and attempts to determine a point away from these actors to move to instead of the actor, so that enemies which are too near other enemies will instead just go somewhere else) but is all not working as expected; the sphere check doesn’t properly follow the actor in question, and often fires very far from the actor’s actual position.

Tutorials are no help here; everyone is keen on demonstrating how to set up good AI for single actors (i.e. patrol, check for ammo, find player, etc) but there’s very little on making multiple actors cooperate in rudimentary fashion (I’m not talking flanking or flushing out or anything like that, just acknowledging when a target is already surrounded and standing still), and what little info is available on crowd navigation seems devoted to “decorative” actors like npc crowds that only exist to be and act like crowds, not using that sort of logic to help a group of enemies behave intelligently.

Hi RhythmScript,

I specifically had in Neverwinter Nights 1 and 2 while making large battles. The auto circling is not a visually appealing melee battle since it just does not happen in a realistic battle. So I set to customizing the AI. In these engines you had functions for proper locations already set up by BioWare and they worked very nicely. I simply had the following to the AI’s code prior to DetermineCombatRound (which happens every 6 seconds or is changed on Death or Blocking or something specific).

  1. Set on 45deg increments around the ‘Target’ that the NPC is seeking. Call them something that represents that position…ShortFwdLeft (1m at 45 to the left, StepLeft (1m at 90 left)
  2. Variable GetIsInCombat bool
  3. Make a small capsule trigger at each of these locations…these should exist for Players and NPCs. These triggers are only used if GetIsInCombat is True
    **These small capsules represent the spacing around a movable object.
    **You can make rings of these small triggers to make sweeping and flanking approaches super simple!! I used 3 rings 1m, 3m, and 5m
  4. Set Heartbeats to the Player and NPCs, 5 seconds for general and 1 or 2 seconds for combat.
  5. For melee simply check to see if a capsule is triggered/occupied and is that an enemy. I would highly recommend Target Locking for 10 to 15 seconds then in the 1 or 2 second combat iteration check to see if things have changed…like the player is kiting the NPCs. If there is a closer enemy switch to it. If not roll a random % to see if the NPC drops pursuit.
  6. For ranged type NPCs and Players there must be a sphere based upon their ranged skill so can auto adjust per weapon and skill type.
  7. For ranged simply check for the enemies inside the sphere to pick a target.
  8. NPCs of the same Faction should always have at least one leader. When there is nothing to do they can always find leader and approach. If the leader dies then simply promote another as leader.

Nice Options to Add:

  1. NPCs shout silently to NPCs within 10m that they need assistance when the health drops below 50% and 25%.
  2. Disengage. NPCs that are below 25% can disengage to find a nearby healer if one exists…if not…FOR GLORY! haha!!
  3. Leaders will Lead meaning they will disengage to allow soldiers to fill slots.
  4. For very tough Players/NPCs the leader can specifically fill all the slots around enemy.
  5. Leaders can call a full retreat if all NPC allies are below 25% and 90% of the enemies are all above 50%

What does is virtually eliminates clumping. The AI is Pathfinding to small capsule locations around the enemy then when in range targets the enemy. There are a lot of things that can be checked for depending which ‘Slot’ is available at the enemy. Say they are 3m out and charging to the StepFwd location/slot…they can leap in and do a smash or something acrobatic. For Flanking and back stabber personalities/behaviours use the outer rings to approach the enemy then turn in. Works amazingly fast and gives the feeling of a savvy AI. The AI also knows to stay in combat mode and wait until a slot becomes available…through player kiting or NPC changing their mind and fleeing, flanking, or death.

Lastly, with 200 NPCs with players smashing each other to bits in one battle there will be little standing around. However, once the battle starts to become one sided then there shall always be standing around. My solution to was always have a Medical NPC and/or Medical Tent near the battle field. Or perhaps if the battle is near a keep then the gate would do the same. If an NPC has not found a slot in ‘Random # Rounds’ let them take off running to the Safe Point and Heal Up then return to the battle (find their leader).

For heartbeat pulse/ticks please see : Persistent Time (many uses for persistent data) FREE! - Blueprint - Epic Developer Community Forums!

I am also setting type of system up in UE4. I have only investigated if the ring locations can be generated…to be honest was very easy in Unity. In UE4 it appears can be all accomplished in blueprints…not certain at point. I would gladly volunteer to work on with you however my UE4 skills are still lacking. Currently tackling animations, emotes, and flickering lighting (candles, fires etc). Working on the AI would still be a great learning experience for certain.

Perhaps if you completed system I would purchase it for certain and many others I should think.

I hope the above helps.

in particular was my bane since the beginning of working in UE4. Since in our project, if group movement didn’t look mildly correct then the entire game itself would be shot. So, my research went all over the place, testing all manner of pathfinding methods, most of which I was able to implement in Unity without much trouble but my woes here are likely as much to do with learning a new system combined with exceptionally rusty C++ skills. In the end, I had to resort to a C++ solution since speed was an for me in BP, or my BP solutions were poorly done…truth is probably a combination of that.

So, I eventually ended up with a Boid solution and site here gave me the key: http://natureofcode.com/ Check out chapter 6. I’d like to plug resource, and recommend supporting the author if you find it useful. Then after finding my solution I solicited help from , which helped unlock my understanding of accessing UE4 nav systems. (, you absolutely rock!) I’m at a point now where my AI moves in groups with a much more natural feel most of the time. All that’s left is a bit of tweaking and optimizing code. (Still struggling with efficient use of Iterators…kinda hoping down the line these will be improved on future releases)

@Krixa - Thanks for that input, really like seeing the mechanics listed out like that, gives me much to think about on my project too!

Edit: @anonymous_user_9c39f750 UE4 Team: I know crowd pathing is still getting tweaks, which I think is going to be super helpful. One of the solutions I looked at involved flow fields, and I still think could have been a viable solution to my needs in conjunction with our targeting mechanics. Might be worth considering, could open the door to all sorts of people looking to build RTS, tower defense, or any game with lots of AI bots running about.

Edit2: Oh, and more specifically on the cannot reach target, which I went off on a tangent over originally… My boid solution also involves varying speeds, so my “still in development” solution has been a combination of slowing AI down to standstill by default. Then I put a public variable on each character that keeps a count going of # enemies engaged, and the AI will check that. For melee characters they will pick a new target if that # is too high and switch to “simple move to” only if it gets a path exists result. If the AI iterates through all the targets and fails on all checks, they kinda just stand there looking dumb. Which isn’t great, but we expect it to be rare if we balance a decent friend/foe ratio.

I feel it might be worth noting, I am NOT doing RTS, but an action game; changes things substantially.

Krixa’s solution, for instance, is extremely clever; but it falls short in a number of ways. One is that MoveTo must be fed an ACTOR to get fluid enemy motion. If you tell an actor to MoveTo a LOCATION, no matter how frequently the location’s value is updated on the blackboard, the AI will carry on to the destination it had when it STARTED moving, until it reaches it.

For an RTS, where the player moved around in discrete movements, isn’t a very big deal; but for an action game, where the player is constantly in motion, telling enemies to MoveTo a location related to him, rather than to HIM, causes the AI to behave stupidly.

One thing I considered doing was trying to dynamically adjust the Acceptable Radius for the MoveTo (i.e. check how many actors are around the player, and use that to increase the acceptable radius so enemies sleep sooner), but again, the problem is that MoveTos don’t like to update mid-move.

I had some issues with myself, which I still cannot fully explain but the look and feel to utilizing moveto location was off. The solution I finally came to was the result of several pathing options. In fact, I think several different methods that are switched on and off might be key for many projects. Anyway, my main movement code now doesn’t find a complete path, but calculates a velocity (rotation/speed) in realtime. So with each tick, it adjusts it’s speed and direction based on what’s going on around it. way I was able to stop pathing method and switch over to alternate methods without any breaks in their previous motions.

Ours isn’t RTS either; however, there turned out to be many mechanics from that genre which translated well to our project. Almost like taking RTS styles and applying it to an adventure game.

Hey RythmScript,
I am sure you have already seen , but is putting together a Dynamic AI Pathing System that could help with the MoveTo Location. It is worth looking through to see how he went about , and perhaps he could even help answer some of your questions as well. His system might be overkill for pedestrian AI, but a simpler version of his system could be exactly what you are looking for.

I had not seen that; is some sort of UE4 storm ninja, and I respect the heck out of him.

Unfortunately, his system is not, you know, DONE; it’s fascinating to watch him at work, but he’s doing stuff that requires C++ to do, which I couldn’t do even if I WANTED to. For the time being I can sort of set my AI to the side and work on other stuff, but I don’t want my project to flounder waiting for to submit his changes or put his work up on the marketplace or whatever.

Fortunately, I don’t want to do anything nearly as complicated or incredible as him… so I’m sure a hacky workaround isn’t out of the question, at least for the time being.

Okay, so I’ve made some interesting progress here, which I feel is worth sharing.

I’ve cobbled together a custom MoveTo Task.

The way it works is, it does an overlap check to determine how many actors are proximal to the player. Every time a new actor gets close, the game widens the radius for “reached actor” and the size of the overlap sphere to check for subsequent actors.

The result is that every subsequent actor can “reach” the player from a further distance.

needs tweaking; what I’d like to do is ultimately create “tiers” for , so that, for instance, we first allow 3 enemies to enter the short radius, then widen the radius substantially and allow 10, etc., to encourage the AI to strafe around and encircle the player rather than forming lines as they currently do.

But it’s at least functional.

EDIT: Though it does have one serious shortcoming; once the radius widens, it stays that way until enemies completely exit it and the checking resets. means once enough enemies get close, the player can simply back up slightly and the enemies will not pursue him. To fix we do a second sphere overlap of a fixed radius (the attackable radius) and check to make sure at least SOME enemies are in it. If they are, we proceed with the above logic; if not, we force the move to continue until at least some enemies are within attack radius.

I disagree with you and you simply missed the point. The AI logic presented is for ANY AI generated game. I was using in Unity prior to coming into UE4…and as stated ran same logic in NWN servers with great success and increased performance. technique also would work in Skyrim, LoTRO, SWTOR, WoW…whatever. Has nothing to do with 1st or 3rd or RTS.

Every postitional combat ‘Tick’ (since everyone in UE4 seems to like word) the AI MUST get the Object that it is Seeking. Perhaps it has a Random Dice Roll and changes its mind? Whatever OBJECT it currently has it simply nabs that location again and feeds that into the Pathfinding logic. The AI is very very fluid and needs very little maintenance. You need to decide how fast that positional combat tick is.

To make happen I created/replicated these Functions in Unity => SetLocalObject(object oSelf, string sVariable) & GetLocalObject(object oSelf, string sVariable). I have not done in UE4 yet but I have an idea how to.
http://www.nwnlexicon.com/index.php?title=GetLocalObject

Once you have the Object you simply get the String (sVariable is the reference ID of that specific object…Object UID) stored on the the NPC (oSelf). Then simply find that matching Object and do what you need from it…or simply clear the Variables and start again.

ends up working almost exactly like timconwell’s method as well. Simple matter to set Blending speeds on the NPC in UE4. 's AI Pathfinding has seriously solved the MoveTo referred to. At some point, when he is happy with it, I shall integrate 's AI Pathfinding into the NPC AI since it functions so well.

In the end you are going to do what you think is best. Good luck.

Well certainly it would be substantially easier to do if I could adjust a MoveTo’s target mid-move, as then I could use a whole network of locations related to the player to instruct enemies.

My point was simply that you could only use MoveTo Location in Unreal for RTS style games (or for stuff like finding cover, which I think is why it was designed that way, since it makes sense for shooters) since the enemy doesn’t like to interrupt its move until it reaches its already-targeted location.

Conceptually I can see how to use what you’re describing to do what I want, but PRACTICALLY it isn’t possible in UE4 that I’ve seen, unless you do like did and rewrite the core pathing logic, since MoveTo commands don’t like to update locations.

EDIT: ACTUALLY, the Blueprint “AI MoveTo” DOES update locations every tick. It’s only the Behavior Tree “MoveTo” instruction that mishandles location data. Which means, Krixa, I’m now going back to re-read your explanation in more depth, because I actually CAN define locations relative to the player and have enemies attempt to move there! It was just a question of determining how to provide the movement command.