Simple AI with Behavior Trees - Agro?

Hi everyone!

So im struggling a bit to make AI, and my struggle is within the Behavior Tree. Im managing to get the AI to follow the player or patrol around the navmesh - basically i’m able to get the AI to execute simple tasks. However, what I want to do is to make the enemies patrol and when the player is within a certain agro range, the AI should follow the player.

How would one manage the behavior tree in this cituation? I’ve tried all the tutorials I could find but I can’t get it to work. I should mention that i’m doing it in the third person example project.

TL;DR - How would I structure the behavior tree when I want AI to patrol around and then execute another task when the player is within a certain range.

Thanks for reading!
Best regards,

Hi ****,

To make this as simple as possible! What I suggest is a sequence node immediately after your Root node. This will allow you to control you execution, and prevent another node from being executed before the previous one finishes.

So in our case we create the first node Attack! which has a Decorator Found Enemy? . This node only executes if an enemy is found. Once an enemy is found, the node shouldn’t finish execution until the enemy is lost. I suggest putting this logic on the Pawn itself. So the enemy check is done by the Pawn, so the Decorator gets that information from the Pawn. Once the enemy is found, the Attack! node assigns a Event Dispatcher which is for your Enemy Lost Event on the Pawn itself. Once the enemy is lost, Pawn calls Enemy Lost. The node Attack! with the Enemy Lost Event Dispatcher Assigned is called finishing execution.

The next node is straight forward, this state gets the next route and moves towards it. Main node should be sequence to allow proper flow execution. Current route information should be stored in the Blackboard Asset.

So the idea is, should I be attacking now? No, keep patrolling. Usually this is the approach for FPS. Shoot or Don’t Shoot is the question.

Thanks,

Peter L. Newton

I agree, I’d just use a Selector where Peter used Sequence, and make the Patrol a Sequence. The main reason for it being that with the original setup you’d end up with the whole sequence failing if “Found Enemy?” failed, unless you added a kind of “always succeed” decorator on top of it. Needless complication. Use this:

I’d also suggest making the “Found Enemy?” condition simple Blackboard-based check if your Enemy key is set or not (and you course you’ll need to be writing your AI’s enemy information into blackboard).

Cheers,

–mieszko

Thank you both very much!

Just a quick question regarding the chart, what node should the found enemy/attack be? Same goes for patrol, is it a selector with a decorator or?

Glackie – were you able to figure everything out?

from my many months of searching no one can make a good aggro system any were its just not possible would love for someone to proof me wrong

1 Like

Now I’m over here searching for ANY reference to building any agro system hahaha the years are not kind!

Here’s how I am doing enemy behavior. I don’t use behavior trees, just blueprint:

A timer drives updates for enemy behavior:

Enemies are held in an array.

First we gather all data necessary to make decisions. This is typically a bool. Can See Player? Close Enough to Attack?

If there is line of sight and we are within the enemies field of view, then enemy knows player location:

In field of view?:
Convert dot product of player location to enemies forward vector to degrees, and make sure it is within a certain threshold. (e.g. ~90-140)


Note the Select on Combat Stance. If my player is in prone position, then I just make the enemies FOV smaller, thus making it less likely to detect the player. I prefer simple logic like this instead of complex simulations, because the only thing the player knows is how likely they will be seen. No reason to over-complicate!

Line of sight?":
A line trace from enemies head bone to the player. I use a max distance so that enemies wont spot you from across the level.

In that case, Is Alerted (e.g. aggro’d) is also true. In my game, I only set this once. Once aggro’d the enemy stays aggro’d.

After data is gathered with which to make decisions with, then we can make those decisions for each enemy:

This is just handled by priority:


Depending on the type of enemy, I branch behavior into a few varieties:

Continuous means that the timer update will keep updating the state. For instance, if we are charging the player, we want to keep updating that so that the enemy tracks players position fast enough.

But if the enemy is currently attacking (playing an attack montage), then we want to gate that off so that we don’t keep calling the montage too frequently. So when the attack montage starts we set a bool to close the gate, and when the montage finish the bool is flipped. Then another attack can happen if we are still going down that branch.

I recommend trying to build a simple system like this first before trying to work with an extremely robust system like behavior tree. For a beginner, BT would be like trying to learn how to drive by piloting an F-22. With a simple blueprint only setup like this, you can avoid the complexities of passing data between multiple classes, and also you can most readily see and understand the execution flow. Whereas if you work with a system built by somebody else, there is a lot of stuff happening that is hidden and you won’t understand.

I find it helpful to verify my logic carefully before diving into code:

If you sketch it out like this and then imagine the execution flow going down each branch, you can catch your logic errors before getting into the weeds with code.

2 Likes