I need help improving my enemy AI code (Top Down Shooter)


#1

Okay, so I might be asking for a lot here. I’ll try to add edits as I make improvements.

I’ve been working on a top down wave based shooter. Right now I’m trying to set up a basic enemy to attack the player, and to get them to attack back. Keep in mind, right now everything is VERY basic. I want to get everything working as good as possible before adding the polish to it and making it look swagalicious. I’ve started off with a very basic spawning system. Just four sprites thrown out of bounds that the game randomly selects from every five seconds and spawns a zombie at.



Now, when the zombies spawn, I want them to move towards the player, and then once they get close enough, attack the player. I also want them to move smoothly, and to feel slightly intimidating. I’ve got some basic code for the zombies, but they have a few kinks and bugs that I need to work out.

The code for the zombies at this point is extremely simple, along with the spawner code


The attack code as well.

Zombies Clustering: This one has been fixed :D

The first problem I have with the zombies, is that they cluster way too easily. When close together, they tend to overlap each other. I tried setting them all as a pathfinding obstacle themselves, but the AI spazzes out when I do that. Is there a way to keep them separate from each other?


Better Zombie AI: In Progress, see future posts below

After that, we have how the zombies move. Right now, they just rush straight towards the player. This works for the most part, but if possible, I’d like for them to seem a bit more lifelike. Maybe once they get into the house, they can randomly search rooms, going to designated points the map before getting close enough to the player and then chasing them down. I feel like I could get something like this running, but it’ll be hard considering the next problem.

The biggest thing impacting me right now is the lag. After adding the basic spawner, the game has been running much slower than usual, especially when more zombies flood the room. It gets so unstable that the player shakes when pressed up against a wall, and can even glitch out of the house. I need help improving this so my game doesn’t end up being too big to run on my own computer.

To make it simple, here’s my to-do list.
:ballot_box_with_check: Keep zombies away from each other
[ ] Make zombies seem more threatening
[ ] Keep game running smoothly as possible

Any suggestions help a bunch, thank you! If you’d like to see any other code or things that might help, feel free to ask, and I’ll post asap!


#2

As someone also making a top-down shooter, I’ve had the exact same issue. I’m still stumped over it and, as spring break’s over, out of time to think about it. I can’t give solutions, but I have thought that might be useful.
You could use “separate two objects”, but that would make their movement very jittery. They would run into each other, then bounce around. The current plan might be to flick around and apply a “mild” force when in collision rather than a sharp separation. But that’s hard to figure out as well.

It might help to further increase the time needed to update AI. Pathfinding seems to me as resource intensive, and 0.2 seconds doesn’t seem as that much time.

For the advanced AI, I would first think of using the same technique as in F.E.A.R. Putting a bunch of flags and triggers everywhere. Have zombie beeline towards house entrance, then change mode of operation to “house searching” and enable pathfinding (this might help with lag, too) Put a flag in every room and give each one name. Then have a list of names in the zombie. If the flag was checked and “move towards”-ed don’t consider it, otherwise randomly pick one. Perhaps only consider a flag if you can raycast towards it without hitting any walls. You can simulate vision with raycasting or simulate a cone of vision with either another object or a check of, say “if angle between zombie and human <30 and >-30”.

Anyways, though I doubt I’m helpful, I wish you good luck with your game, if found pls send clustering solution, and send events thx.


#3

Keep zombies away from each other

I’m not sure why setting the zombies as path blocking objects as well as pathfinding did not work… that might be worth setting up a small project to debug that.
Otherwise I think a simple condition like “collision zombie zombie -> separate objects zombie zombie”
If that’s too slow then you can try doing that only for each zombie while you are moving it.

Make zombies seem more threatening

Add a view cone to each zombie.
If the zombie’s angle to player is smaller than the view cone angle and the distance to the player is less than some amount, and there is no raycast to a wall between the zombie and the player THEN play a scary sound and increase the speed of the zombie, and maybe change it’s color.
This will make it feel like the zombies have found the player and become enraged. Should lead to player’s feeling like they can hide behind walls and such.
You could also add a “hearing” radius for zombies, and a “noise” radius for the actions the player does like shooting and walking. Then if a noise radius ever overlaps with the hearing radius of nearby zombies they will try to head to the center of that noise radius.

Keep game running smoothly as possible

Use “Groups” for ALL of your different pieces of logic.
Give the groups appropriate names.
When you run the game in debug mode, you can use the performance profiler and it will tell you which GROUPs of logic are taking the most time.
In general try to use selectors instead of for each loops, also when you have multiple conditionals in the same block but the simple ones first.


#4

Apologies for the late response, I’m about to graduate and I’ve been trying to catch up on several assignments. I tried adding separate objects zombie zombie and it works, kind of. They press right up against each other front to back and sometimes I’ll kill one and the other will delete with it like the merging glitch, but it only happens occasionally, and they’re still separated, so it works for me!

@Sciller4
I combined your last two ideas, and made a brand new system. It still kind of lags, but the game still seems to run without too many glitches or noticeable frame drops. I decided to add flags in the rooms of the house, that when the zombies spawn, they’re sent to a random flag.
bait
I just made about four of these and put them in the corner rooms. Then when the scene starts, I just hide them. (It’s the same map, but this game is also being made for class credits, so I need to get it completed soon, so I’m just continuously developing the game and then going back to fix broken and janky code later.)


This code takes care of all the spawning and how the enemies track you down. For the sake of quickness and keeping it lightweight at the moment, I made it so once the zombie spawns, it just sends it to a random flag. I used to have some code so that when it hit one, it would then select another flag and then run towards a new room continuously until it hits the player, but it didn’t work, and just ran in and sat at the bait, so I took that part out. Instead, I have the game measure the distance from them to the player, and if you get close enough, they begin to chase you, so you can sometimes look over and see one or two waiting in a room, but once you get close, they chase you, balancing difficulty a bit if you’re cornered in a room and more are spawning in, and most of the time it just seems like they walk in and then begin to attack immediately so it works well for an alpha, I’ll continue posting my progress with it when I add more.

@krunkster
I ran debug mode for an average play session of my game, this is what I got back


Events and Objects seem to be the ones that take up the most processing power here. Render does too, but it doesn’t have any sub categories, so I’m not exactly sure what that is, my guess is it’s just how much it takes to render the graphics on screen.

In events, AI and Collision take up the most power, as expected. Other than that, everything else seems fine, I could probably skim down the code for all the weapons though.

Here’s objects. Pathfinding takes up some power, but the pathfinding obstacles seem to take up more. The platformer object is the player. It’s top down, but I also made it a player character and then turned off the controls for it for easy collision for the player and the walls. I’m not sure why health takes up so much either. It might be because it’s referenced for every character on screen in collisions.


#5

I made my own horde shooter prototype yesterday and I’m seeing a lot of the same problems that you are with collisions and pathfinding. At this point I believe that the pathfinding behavior is potentially only reliable for static obstacles. It also seems that once a path is locked in the path finding will not adapt to any new obstacles or changes along the path.
I’m not sure how to accommodate for this yet.


#6

Here’s how I resolved this problem for my prototype:
Create a group for all “Pathfinding Obstacles” called Obstacles
Create a state machine for your path finding objects (mobs):
Have the mobs start in an “idle” state
When you see a mob in an “idle” state, put it into “searching” state and use the pathfinding command “Move to location” to where you want it to go. Start a search timer on the object.
When you see a mob in “searching” state check to see if a path was found, if so stop the timer and put the mob into “normal” state. If not check the search timer, if it’s been more than half a second then try to move the mob again using path finding, but this time add some random ness to the X and Y. If the search timer is greater than 1 second then put the mob into “stuck” state. (up to your game design on what to do with stuck mobs… you could just cycle back to “idle” state too).
Create a condition:
If Mob in collision with Obstacle => Separate objects: Mob & Obstacles (Obstacles won’t move), and put the Mob into “idle” state.

If you can grok all of that, it works essentially how you would expect and the path finding actually goes around the moving obstacles instead of through them.


#7

I was having the same kind of issues with the pathfinding behavior and the lag was ridiculous. So I just disabled the behavior and applied force to the objects to move to several sets of coordinates. Not ideal, but my game runs perfectly now so oh well. Haha. I guess the pathfinding behavior is just buggy? I’ve never been able to get it to work properly.