How can I create enemy AI?

Hello.

Today I decided that I was going to create the AI for my enemies, but after attempting it, I feel completely lost.


Now I’ve got pathfinding working just fine right, but the problem with the path finding is that if the player moves it well doesnt update, and I feel like constantly calling the :ComputeAsync() function might start causing lag, especially when theres a lot of enemies.


So I thought Id just make it so when the players insight, th enemy just uses MoveTo() but that required a raycast, and every time the player moves, Id have to raycast again just to update it, that again with all the enemies might be costly (Im not actually sure how much stuff is being taken up so uh yeah if you know how, that’d be appreciated.

So long story short, Im really confused on what to do, so any ideas on how to create this system to be as optimized as possible, without it working poorly would be deeply appreciated!

Thanks :]

1 Like

Using raycasts too much isn’t a bad thing. I have used AI enemies that repeatedly check using raycasting. I never tried using :ComputeAsync the same way, but I’m pretty sure it won’t be an issue either

1 Like

Hi there,

For any type of performant enemy AI system, you need to make sure the clients do all the rendering of the enemy movement and animations, and the server just calculates the position that the enemy should be at for the clients to visualise. On the server, the enemy should just be a simple array or instance of an enemy class (if you are using OOP), which contains important server-managed information like the health, position, debuffs and more.

If you want your system to be performant, you should not use humanoid moveTo, instead you need to use some sort of constraint based physics system (via align orientation and body velocity), or linear interpolation/tweening between given points. Its also important to make use of parallel Lua, using separate threads on the server to execute enemy AI logic (using finite state machines) and calculate movement positions – this would allow you to handle lots of AIs at once. Its also worth to note that depending on what kind of game you are making, you can implement different ways of further improving performance: for instance, in a TDS game, you could omit the y-coordinates of the enemies which would reduce the positional data by a third.

You can also implement further performance optimisations like only rendering enemies in a clients FOV, and also using client side-prediction to improve server/client desync – these are only a couple, but there are a lot more you could add. However, this aspect is more if you want to squeeze as much performance as you can, just focus on getting the main system to work and then look at these.

2 Likes

Just a question, if the client is too do all of the rendering and stuff, how would I go about constantly updating the client with new information regarding all of the NPCs?

Just wondering if you have any ideas for a starting point for creating this stuff, thanks!

I would send a remote event every 0.2-0.1 seconds (don’t to every heartbeat as this would be too much) from the server to the client containing the new position of an enemy, and the client would then move to that position through your chosen method. On enemy creation on the server, you should send a remote event to the client to actually put the enemy in workspace, and assign values like its speed and other data that would be needed for client visualisation. I would then have a seperate remote event for playing new animations, and this would be handled by a animation handler script on the client. There are lots of ways to optmize the positional data sent from the server to the client, and you can find many resources on the devforum and elsewhere on that topic.