Is there any competent Zombie AI?

Welcome to our brand new Clickteam Community Hub! We hope you will enjoy using the new features, which we will be further expanding in the coming months.

A few features including Passport are unavailable initially whilst we monitor stability of the new platform, we hope to bring these online very soon. Small issues will crop up following the import from our old system, including some message formatting, translation accuracy and other things.

Thank you for your patience whilst we've worked on this and we look forward to more exciting community developments soon!

Clickteam.
  • For my next game I want to make a zombie game so of course I need to have a Zombie AI. I have never done an AI of this sort though so I am trying to find examples on how to do it. I have looked at some examples and bought a couple on the clicker store, but all of them have serious flaws that would not make them quite the quality for a proper game that is sold on Steam etc.

    Most importantly I need a zombie AI that make the zombies able to get around walls without trying to "push" their way through the wall and slide a long it until they reach an exit. They should be dumb (they are zombies), but still be able to traverse around the environment.

    Have anyone dibbled in this and know if there is any competent zombie AI examples out there or what would be the best steps to try to create one? Are some extensions essential if trying to do such a task?

    Steam games: Please login to see this link.

    Edited once, last by Outcast (February 20, 2020 at 11:33 AM).

  • Hi Outcast.

    Yes I have dont a lot of AI in the past....and there is an easy way to do it...But remember AI is always designed around the need of the game (ISO, 3D, 2D, Top Down, etc etc)

    Instead of using collision detection (IE: the slide-around-it thing you mention) you can use a much older method, but one that still works perfectly.

    All you do is to map out your ground area and the obstacles, and simply save it as a binary.
    So as an example....Here is a 9 by 3 play area:

    123456789
    000000000----1
    000010000----2
    000000000----3

    What you would then do is to keep track of your zombie and what area it is in.
    So in the above example, lets say your zombie is at position 3,2 then he ( X ) would be here:

    123456789
    000000000----1
    00X010000----2
    000000000----3

    When your zombie gets to 3,3, he will be next to the obstacle, so you can then give him a random direction to move (up or down) to get around it. You then move the zombie in that direction and so avoid the obstacle.

    Yes it does mean you have to add a few variables (counters) to your game, but once you have it working, then you will find that your zombie can home-in on the player and totally avoid the obstacles without a problem.

    If you want I can make you a very simple example to help you...but I may have to post it tomorrow as im busy today. :)

  • I'm in the process of making AI for my game, so I'm also very interested in seeing what suggestions people have. I think environment navigation is just one part of the problem (albeit probably the most fundamental part). Even for a dumb enemy like a zombie, I think you probably need to factor in quite a lot of things before they feel believable (ie. the zombies seem dumb rather than the game seeming dumb). Here are some I think would be useful:

    -keep track of distance to player and only chase player if at a reasonable distance
    -keep track of line of sight and only chase player if appropriate
    -detect holes/inaccessible terrain in between player and enemy and don't bother chasing if player can't actually be reached.
    -if enemy has a 'frenzied' state when chasing player, include some sort of cooldown timer so that enemy isn't frenzied forever
    -include some basic geometry/algebra in chasing routine so that enemy doesn't just run to where player is but to where player is likely going (eg. if enemy is at 9o'clock and player is at 3o'clock but moving south, enemy should move not east but southeast)
    -include some basic record of enemy's recent movement patterns, so that if they have been going around in circles or bouncing between two points for a long time, they'll try something new to break out of the pattern*
    -include some occasional check to see if enemy is stuck in a wall or glitching out some other way, with some strategy for fixing them up (eg. moving them X pixels away from the wall until they get unstuck)
    -some kind of randomised 'personality type' or some such thing that tries to make different enemies behave slightly differently, so that the player doesn't end up being like the Pied Piper with a conga line of automatons following him around all in exactly the same way


    * Here's an issue I recently found that I hadn't expected at the planning stage, but that became immediately apparent once testing began (I imagine many more issues like it will surface eventually). Some of my enemies can jump onto ceilings and move on them. So I had their movement set like this:
    -they move along a ceiling until they get to an edge
    -once at the edge, they test to see if they can safely drop down to a nearby ledge
    -if not, they turn around.

    But then you get a situation like this where the enemy gets stuck in a loop on a ceiling, because it only checks for dropping points when it's at an edge, but the only safe dropping point occurs away from the edges:

    Please login to see this picture.


    So my solution was to keep track of how many times it hits ceiling edges consecutively, and force it to look for a dropping point once it hits a certain amount of them:


    Please login to see this picture.

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • I am considering between ISO and complete top down, but I think I will go for the complete top down since it would simplify things a lot I imagine and this is a completely new genre for me to tackle in many other areas (like with the AI), I think it would be easier with top down, not the least with graphics and animations for characters with having to just have a top down sprite instead of a 8 direction sprite from all angels. I have not fully decided yet though since I find that making graphics for objects from a completely top down perspective is a little tricky in its own right since it is quite an odd angle to see things from and many things look very "strange" from a complete top down perspective.

    If you would like to make an example of your method I would gladly try it :)


    ]

    Happy to see that Spryke is still going forward :)

    I can imagine that making AI is a sure way to get a lot of unexpected results and problems to overcome in ways that no other area of development has!

    One other area I am a little worried about is how performance heavy AI could potentially become, especially if having like 100 zombies. I even toyed with the idea of wanting to have the whole map be active and "moving" in real time all the time, so like zombies that are way far away from you are still moving around, I like that sort of persistance in games where not everything is just happening right around the player and everything else is "freezed" or just an "illusion", even if it is in practice "pointless" in a way. But I imagine that would make it even more performance heavy.

    Steam games: Please login to see this link.

    Edited once, last by Outcast (February 21, 2020 at 10:42 AM).

  • What you're talking about is "collision avoidance" (that's the proper term to google), as opposed to true pathfinding.
    Dex's method seems like it should work.

    Alternatively, I remember seeing an example many years back, that used two detectors positioned in front of the zombie, at roughly 2 and 10 o'clock positions.
    If only the 10 o'clock (left) detector overlaps an obstacle, rotate to the right (clockwise).
    If only the 2 o'clock (right) detector overlaps an obstacle, rotate to the left (anti-clockwise).
    If both detectors overlap an obstacle, pick a direction (clockwise or anticlockwise) and keep rotating in that direction until not overlapping a backdrop.
    If neither detectors overlap an obstacle, rotate towards the player character.

    It's very simple, but it does work - although it requires a bit of fine-tuning to get the best results.

    I couldn't find the original file or forum post any more (might have been on The Daily Click?), so I've just put together a quick example to demonstrate the principle.

    Please login to see this link.
    (arrow keys to move the player)

    Obviously that's just the collision avoidance part - you still need to add in line-of-sight calculation (loads of example on the forums) and some behavioural states (searching, chasing, going to last known position, etc).

  • One other area I am a little worried about is how performance heavy AI could potentially become, especially if having like 100 zombies. I even toyed with the idea of wanting to have the whole map be active and "moving" in real time all the time, so like zombies that are way far away from you are still moving around, I like that sort of persistance in games where not everything is just happening right around the player and everything else is "freezed" or just an "illusion", even if it is in practice "pointless" in a way. But I imagine that would make it even more performance heavy.

    I've been very concerned with this too, especially since overlap checks are so expensive. I've been mindful of performance/efficiency since the beginning, and so far I've been relieved to see that performance is very acceptable. I only check for collisions only every 2nd tick or so, and only basic collisions (eg. is a hole or wall present, is enemy on a slope); only if a hole or wall has been found do I check detailed collisions (how wide is the hole, how tall is the wall, must enemy adjust for slope etc.).

    If you have the whole map active, I'm sure you can somehow simplify the AI for those zombies that are off-screen or far away from the player - maybe check them less often, or use basic XY calculations rather than actual overlap checks, and of course skip any animation/rotation stuff for zombies that aren't currently visible. I'm sure this is what many AAA games do - especially open-world ones. I'm pretty sure I've taken advantage of this recently when playing Borderlands 3: some enemy had glitched and disappeared - stuck in geometry or whatever - so I moved as far as I could to the other end of the room. When I came back, he was fixed...I'm assuming it's because his AI routines changed when I was far away, and were perhaps more forgiving of collisions, allowing him to return to where he was meant to be.

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • Quote


    Quote


    Wow, that seems to actually work kind of good! (apart from the "zombie" being a bit "jittery" for some reason, but that might be curable?)

    The only main concern with this I have is what Volnaiskra is also saying in that overlap checks are expensive so maybe it would be too performance heavy to do it this way with too many zombies?

    Steam games: Please login to see this link.

  • Yes, fine collision checks are slow. On the other hand, bounding box collision detection should not be computationally expensive at all, so try disabling fine collision detection in the object properties.

    Alternatively, there are two other routes you could go:

    You could make the game grid-based, so collisions can be detected simply by looking up values from an array - Dex has suggested one way of doing that, but actually almost any method that works using the built in collision detection could be adapted to use an array instead (including the example I posted above).

    You could make the game polygon-based, so collisions can be detected by calculating the intersections of lines. The maths is a bit more involved, but polygonal maps lend themselves really well to much more efficient pathfinding, line-of-sight checks, shadow-casting, etc and allow a more "free form" level design than is possible with a grid, so there are a lot of added bonuses.

  • Yes, fine collision checks are slow. On the other hand, bounding box collision detection should not be computationally expensive at all, so try disabling fine collision detection in the object properties.

    Alternatively, there are two other routes you could go:

    You could make the game grid-based, so collisions can be detected simply by looking up values from an array - Dex has suggested one way of doing that, but actually almost any method that works using the built in collision detection could be adapted to use an array instead (including the example I posted above).

    You could make the game polygon-based, so collisions can be detected by calculating the intersections of lines. The maths is a bit more involved, but polygonal maps lend themselves really well to much more efficient pathfinding, line-of-sight checks, shadow-casting, etc and allow a more "free form" level design than is possible with a grid, so there are a lot of added bonuses.

    Yes, I don't think I will go the grid-based route though, unless it is possible to have really tiny grids? I don't want the movement to be "locked" and moving like on a checkers board. With polygon based do you mean 3D?

    Another route I have been considering is doing things with Box2D since that could possibly make for cool effects with zombies being able to move around furniture etc. I wonder if it would be possible to make a similair system that you had for traversing movement, but based on Box2D? Perhaps that would not be as performance heavy?

    There was an example of a zombie game with Box2D that was kind of cool, even though the pathfinding on the zombies did not seem as good as in you example, but the source code seems to be gone :/

    Please login to see this link.

    Also a video of the game: Please login to see this link.

    Steam games: Please login to see this link.

  • By "grid-based", I don't mean that the actual movement has to be grid-based - only that the map is grid-based. That way, a two-dimensional array can easily be used to label a grid space as either walkable or an obstacle. With a little more work, you could also implement simple shapes such as circles and 45 degree angled walls, to give you slightly more fine control. In terms of creating the graphics, designing maps, saving and loading map data etc, a grid-based system will be much easier as well. This is the way I would go, in your particular case, since it's also good for stuff like destructible terrain and movable barricades etc, which I'd guess you might want to include.

    By "polygon-based", I don't mean 3D, although the vast majority of 3D games are polygon-based, and so very often use polygons in their pathfinding etc, because most of the groundwork is therefore already done. All I mean is that obstacles are defined only as a list of vertex (corner) positions, and the outline that they form - collisions can be tested for using just maths (involves intersecting line segments). This would be massively more work (to be honest, don't even bother unless you're very confident with geometry and vector maths), but would give the best looking and performing results - if you can avoid bugs...

    Please login to see this picture.
    On the left is a polygon-based pathfinding system I made (but never quite managed to iron out all the bugs in). The example on the right was designed as a polygon-based field-of-vision display, like in "Commandos : Behind Enemy Lines", but it could easily be used for lighting/shadows too. In both, the shape of the obstacles is defined only by a long string of successive vertex coordinates, stored in a list or an alterable string - the visible lines and numbered nodes are only there for debugging purposes, and are not used in any of the calculations at all.

    Box2D is likely to be far more computationally expensive than any other alternative.

  • By "grid-based", I don't mean that the actual movement has to be grid-based - only that the map is grid-based. That way, a two-dimensional array can easily be used to label a grid space as either walkable or an obstacle. With a little more work, you could also implement simple shapes such as circles and 45 degree angled walls, to give you slightly more fine control. In terms of creating the graphics, designing maps, saving and loading map data etc, a grid-based system will be much easier as well. This is the way I would go, in your particular case, since it's also good for stuff like destructible terrain and movable barricades etc, which I'd guess you might want to include.

    By "polygon-based", I don't mean 3D, although the vast majority of 3D games are polygon-based, and so very often use polygons in their pathfinding etc, because most of the groundwork is therefore already done. All I mean is that obstacles are defined only as a list of vertex (corner) positions, and the outline that they form - collisions can be tested for using just maths (involves intersecting line segments). This would be massively more work (to be honest, don't even bother unless you're very confident with geometry and vector maths), but would give the best looking and performing results - if you can avoid bugs...

    Please login to see this picture.
    On the left is a polygon-based pathfinding system I made (but never quite managed to iron out all the bugs in). The example on the right was designed as a polygon-based field-of-vision display, like in "Commandos : Behind Enemy Lines", but it could easily be used for lighting/shadows too. In both, the shape of the obstacles is defined only by a long string of successive vertex coordinates, stored in a list or an alterable string - the visible lines and numbered nodes are only there for debugging purposes, and are not used in any of the calculations at all.

    Box2D is likely to be far more computationally expensive than any other alternative.

    Ah thank you for the clarification! I see what you mean now with the grid based system and it does sound like a good idea. Where would I start though if I have never done such a system before? Would it be possible to do an AI system like you did with the overlap of obstacles with no overlap checks this way you mean then? Not sure exactly how that would work?

    Also when it comes to movable barricades, how would a grid based system work in that case? Do you think it would be possible to use a grid based system and still use Box2D for movable objects?

    Steam games: Please login to see this link.

  • Oh, and there's also the background collision mask on those runtimes that support it. That should be very fast as all it's doing is reading 2-bits of data (although you do need to calculate the position to test). It's basically the same as using 1x1 pixel detectors, but probably a little faster. Destructible terrain is easy, but for movable objects (eg. crates that can be pushed around) you'd still need actives and normal collision detection as well.

    And yes, if you've got a large map and huge numbers of zombies, there's nothing wrong with using a less accurate but more efficient method for the zombies that are out of sight. If you were using the array based method I suggested, you could easily have the zombies that are too far away to be visible using a simple and very fast grid-based movement (jumping whole tiles in one step), and then have them switch to pixel-perfect movement once they get closer to the player.

  • Oh, and there's also the background collision mask on those runtimes that support it. That should be very fast as all it's doing is reading 2-bits of data (although you do need to calculate the position to test). It's basically the same as using 1x1 pixel detectors, but probably a little faster. .

    Hmm sorry but I don't understand this, what do you mean by background collision mask and that those runtimes support it? All this is all completely new to me :) My biggest issue though is that this sounds good in theory to me, but I have no clue where to start if I actually wanted to try to implement something like this and what objects and extension I need (if any) etc (I assume I need to use the array object?), is there any tutorials or examples out there on how to do this?

    Steam games: Please login to see this link.

  • The collision mask feature allows you to test any pixel to see if it is an obstacle:
    Please login to see this picture.
    Please login to see this picture.

    From the help file:

    "Value of collision mask. This function asks for two parameters : X and Y position of the pixel to test. It returns 2 if the given pixel is located over a ladder, 1 if the given pixel is located over an obstacle and 0 if the pixel is located on a free area."

    "Collision Mask
    Is Obstacle tests the collision mask for the presence of an obstacle at the given X and Y coordinates. This condition is true when the coordinates lay over an obstacle.
    Is Ladder tests the collision mask for the presence of a ladder at the given X and Y coordinates. This condition is true when the coordinates lay over a ladder."

    I don't believe it's supported in all runtimes though, as I think in some runtimes backdrops are handled more like actives.


    Yes, you will need an array, but no other extensions. Personally, I would create a tile-based level editor for making the maps (it'll save you loads of time in the long run), and have it save maps as array files - and you can store the collision information in the same array.

    My previous example, but converted to use an array instead:
    Please login to see this link.
    If you're not going to have a *huge* number of zombies on screen at once, I'd probably use whatever method gives the best looking results, even if it's quite heavy in terms of performance - and then focus on trying to make the movement of the zombies that are further away as efficient as possible (probably grid-based).

  • Quote


    Oh, I had no idea there was such a thing as Collision Mask. So if I understand it correctly you "assign" some pixels a value of 0-2 and then you can test against those pixels? How do you assign those pixels though if you say have an active object that is a wall, how to assign the pixels at that wall to be an obstacle? (EDIT: Ah I think I saw where you did write them as 1:s now over the backrops in your example)

    Also "ladder" is that just a term for something that is not either empty or an obstacle? It does not have anything to do with actual "ladders"? So in my case for example I could have solid walls as obstacle "1" and destructable doors and windows as "ladders" "2"?

    About performance etc, perhaps it would be easiest to just do simple overlaps for the things that are on the screen yes. I am not exactly sure how perormance heavy things can get, I mean we still talk about a low res 2D game (?) and I will be targeting the PC market. I have no plan to make this for mobile or other more performance sensitive devices. But then again, I don't know if things still could get heavy.

    Btw, do you have any idea how you would go about tackling zombie to zombie interaction? Of course as it is now with a system like this all the zombies can "clump togheter" in one spot on top of another so I need to have some way to check so they don't walk over each other. I was thinking about something like assigning an ID to all the zombies and then if two zombies collide the one with the lower ID will stop and the other one will move until they no longer collide if something like that would work and be a good method ? Then again while just thinking on it I can imagine all sorts of bugs with that though if there is like a big group of zombies with high IDs around a group of lower zombie IDs, then they would never get out of that group surrounding them.. hmm maybe not such a good method

    Steam games: Please login to see this link.

    Edited once, last by Outcast (February 23, 2020 at 4:57 PM).

  • The collision mask is very much integrated into CF2.5. When you create a backdrop or quick backdrop, or when you use the "add to backdrop" action of an active object, you can choose to make it either "obstacle", "platform" or "ladder". Obstacles are used by all the built-in movements (and the "overlapping a backdrop" condition), while platforms and ladders are only used by the built-in platform movement. The way CF2.5 works behind the scenes, is that it creates a big map of the frame, called the "collision mask", and uses it to store the backdrop type of every pixel (obstacle, platform, ladder or empty). If you've got a lot of objects whose shape and position never changes (ie. backdrops), then using a mask makes collision detection much faster than it would be if you were to individually check for collisions with each one, so that's why Clickteam did it.

    Unfortunately, I think you've hit the nail on the head at the end there. By far the most difficult thing is going to be keeping the zombies from overlapping - it's massively more complicated than it might seem, and a good reason why you *might* need a physics extension.

  • The collision mask is very much integrated into CF2.5. When you create a backdrop or quick backdrop, or when you use the "add to backdrop" action of an active object, you can choose to make it either "obstacle", "platform" or "ladder". Obstacles are used by all the built-in movements (and the "overlapping a backdrop" condition), while platforms and ladders are only used by the built-in platform movement. The way CF2.5 works behind the scenes, is that it creates a big map of the frame, called the "collision mask", and uses it to store the backdrop type of every pixel (obstacle, platform, ladder or empty). If you've got a lot of objects whose shape and position never changes (ie. backdrops), then using a mask makes collision detection much faster than it would be if you were to individually check for collisions with each one, so that's why Clickteam did it.

    Unfortunately, I think you've hit the nail on the head at the end there. By far the most difficult thing is going to be keeping the zombies from overlapping - it's massively more complicated than it might seem, and a good reason why you *might* need a physics extension.

    Ah thanks I think I get it. So in performance from slowest to fastest when checking collisions would it be actives -> backdrops -> collision masks? The thing I don't get though is if collision masks is so much faster than backrops why are not all backrops automatically made into collision masks on runtime since backdrops are static and never move?

    If I went with the Box2D way do you think I still could benefit from using Collision Masks?

    I am thinking if it would potentially be possible to have the same logic you had in your example with turning the zombies when detecting walls, but by using physics shapes and apply force in a direction to make the zombies turn and behave in roughly the same way, but with physics and all the benefits that come with that with automatic "collisions" between bodies so they dont overlap..? Or do you think there would have to be a completely different way to approach it?

    Steam games: Please login to see this link.

  • In terms of zombie/zombie interaction, Maybe a bit of randomisation would help prevent zombies being trapped or in perpetual loops (if randomisation would be acceptable for your game type) . For example:

    Every so often, randomly swap IDs of two zombies.
    Every so often, randomly pick a zombie and give him a new, random target to walk to (thus potentially moving him away from a traffic jam)
    Every so often, temporarily disable collision checks for one zombie, allowing him to move through other zombies.

    You could perhaps apply some basic heuristics to this kind of thing. For example, periodically record the x and y values of each zombie. Then occasionally compare the last, say, 4 records; if the x and y values haven't changed much in that time, assume that the zombie is likely stuck somehow, and give him one of the 'rule-breaking' behaviours I listed above

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • In terms of zombie/zombie interaction, Maybe a bit of randomisation would help prevent zombies being trapped or in perpetual loops (if randomisation would be acceptable for your game type) . For example:

    Every so often, randomly swap IDs of two zombies.
    Every so often, randomly pick a zombie and give him a new, random target to walk to (thus potentially moving him away from a traffic jam)
    Every so often, temporarily disable collision checks for one zombie, allowing him to move through other zombies.

    You could perhaps apply some basic heuristics to this kind of thing. For example, periodically record the x and y values of each zombie. Then occasionally compare the last, say, 4 records; if the x and y values haven't changed much in that time, assume that the zombie is likely stuck somehow, and give him one of the 'rule-breaking' behaviours I listed above

    Yes that would also be a way to minimize bugs! But honestly I am quite inclined to go with Box2D to get the zombie to zombie collision thing kind of sorted by itself, and nice physics when it comes to moving objects around never hurt.. the only problem then would be to have them still navigate around obstacles in a way that is acceptable like in the example by muddy mole.

    Steam games: Please login to see this link.

  • Would it be feasible to use something similar to boids to handle zombie groups? Only without the flock "cohesion" effect?

    There's a video here about the concept with info in the description: Please login to see this link.

    And I believe there is a fusion extension called "Flocking" that implements this here (not sure about obstacle avoidance): Please login to see this link.

    Best person at writing incomprehensible posts. Edits are a regularity.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!