AI optimization

I need at least a hundred AI characters in my game. However this has a huge impact on performance. I know it’s not the character models because having AIs without mesh impacts the performance just as much. Is there any known ways to reduce AI performance impact?
I’m pretty new to Unreal so I don’t know much about it’s features. I do however know that you can use behavior trees to create AI behaviors. Right now I’m using blueprint for that so maybe that’s the problem?
The behavior is really simple though. It just moves the character on a nav mesh and updates the destination every 10th second. No tick calculations or anything.
I’ve read somewhere that the character movement component is pretty expensive. Could that be the problem? Is there a good alternative component to use for movement instead?
I know that Unreal has some kind of AI crown feature. Is this something I could use?

Are you using an AI Move To node or just adding input movement directly? Can you post a screenshot of your BP?

a couple of screenshots are a attached to this reply. As you can see, I use the AI move to node and now heavy calculations are done. No tick event or anything that I know is heavy on the performance.

Byt that’s weird because in another project, I made AI characters that use the character class as parent and I could spawn hundreds of those.

I’m having a similar issue. I believe, by using the profiler, that the movement component is the issue. I’m not sure entirely how to address it.

It’s possible to have a very large number. However, for me, they only begin lagging when movement is requested - pathfinding or otherwise.

Have you found a way guys ? I am struggling with the same problem and I see that I am limited to ~ 40 characters right now and yes movement is the problem that takes the whole CPU time.

I am also trying to solve this. I have very simple zombies using move to player location. Is there a more cost effective way of doing this?

Consider moving your AI from Blueprints to a Behaviour Tree based solution, even if it’s just using Move To. iirc, the behaviour tree Move To node is capable of running the nav query over multiple ticks so the performance impact won’t be as drastic.

On a side note, if @MieszkoZ still hangs out in the Answer Hub he should have some much more detailed advice as to how best to optimise that sort of thing.

Yeah, I solved this, but you will have to get your hands dirty woth c++ for it to work
I’m having around 200-250 characters now.
I had to subclass CharacterMovementComponent and then apply Occlusion Culling to it’s
movement Ticks.

In General Indevided Characters in to Several Groups (so they’re movement components won’t tick togethere once they are not visible).
In character Tick I querrt if they are visible on the screen - if yes then I let it’s movement component to tick normaly, if not I stalling the CharactersMovementComponent Tick (while still calculating the right delta time) So in case that character is not Visible on the screen it will tick once in a while nit woth a proper DeltaTime - so it won’t kill the movement accuracy and tine.

Mine is already in a behavior tree.

Not afraid to get my hands dirty. Any chance you could post some scree Caps or something. I’m haven’t done any c++ in ue4 yet. I’ve done some outside though, so I could probably find my way around looking at it.

I’m working with wave based zombie ai for a VR game on a procedurally generated map made with dungeon architect. My nsv mesh is built on runtime. Not sure if any of that changes the usefulness of the advice at all.

There are hitboxes on mine so they can ragdoll and also to determine how many points to award per body part shot. Limb, body, head, etc.

Well That can slow down your character as well,
I suggest to dump the hit boxes and to work directly withba mesh bones,
it will require some more work to map all the bones to the points - bit shall increase your movement performance .

I had suspicions of this. The character is a lightly modified version of the zombie from weapon master VR. I’ll let him know about it too.

But wait with that, I will post some code snippets when ai will be back at home,
try to implement it, and measure the performance maybe it will already satisfy your needs.
(Since you didn’t say how much characters you want to have on the screen).

At least 100 zombies at a minimum 90fps in an procedural open world with physics

I will post some code later on today.
Well in General I’m also playing with RVO (toggling on/off)
My nav mesh also rebuilds in runtime (I am using distructible environment)

Oh one last thing - I am also not using any collision spheres or something like that on a characters
all the AI detections happens on a separate thread.

Ok, so here you go:

You have to create your own CharacterMovementComponent:
And add to it’s header:

UCLASS()
class YOUR_GAME_NAME_API UCM: public UCharacterMovementComponent
{
	GENERATED_BODY()

protected:
	//Init
	virtual void InitializeComponent() override;


public:

        //Useful to make sure that your characters are using the correct Component.
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = StubCheck)
	bool m_dummyToMakeSure; 

	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;

private:
	float m_DeltaTime;
	int m_nTicksCount;
	int	m_nTickGroup;

	bool m_SkipFloorChecks;
};

In the CPP

void UCM::InitializeComponent()
{
	Super::InitializeComponent();

	m_nTickGroup = FMath::RandRange(3, 4);
	m_DeltaTime = 0.0f;
	m_SkipFloorChecks = FMath::RandBool();
	m_nTicksCount = 0;
}

void UCM::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
   	m_DeltaTime += DeltaTime;
	if (!CharacterOwner->GetMesh()->bRecentlyRendered)
	{
		if (++ m_nTicksCount % m_nTickGroup == 0)
		{
			m_nTicksCount = 0;
			DeltaTime = m_DeltaTime;
		}
		else
		{
			return;
		}
		
	}

	m_DeltaTime = 0.0f;

	//Call Default CharacterMovementComponent
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

This code snippet will cull of some of the Movement Component overhead for an invisible Characters.
Theoretically it should increase the number of Characters (that are off-screen) twice.

Please refer to this Wiki Page: on how to create a custom CharacterMovementComponent

2 Likes

This is pre your fix. I get about 40 fps here with 80 ai. Gunna put in your fix and see what happens