Σελίδες

Τρίτη 5 Ιουνίου 2018

C.L.A.S. A flexible design pattern for video game AI.

AI for video games can become a complex and frustrating thing to make. It is something that can become overwhelming relatively fast enough for the developer that is tasked to implement it. Back when I was working on my cancelled RPG project I had to deal with the problem of creating a complex AI myself. I had to drop the work I had done and redesign the AI system from scratch a number of times, because as I added more and more features, complexity would grow so big it would become chaotic to work on it. Eventually I ended up with a design that kind of work best from everything I've tried. Although I gave up on making a huge RPG all by myself and decided to work on a smaller, more manageable project (a FPS), I decided to use the general design I had used for the RPG, on the FPS, because I knew that this particular design scales well, even though the AI complexity of the FPS I'm currently working on won't reach the levels of the RPG. So I noticed that I was using a pattern, a design pattern specifically for video game AI but I didn't gave a lot of attention, until today. Today I read a thread on r/gamedev where someone shared his personal adventures of trying to work on AI. I realized that other people might not come up with a system like my own or perhaps something different that it suits them anyway, so I thought that it might be a good idea to share the design pattern I came up with, because it might help some people.

The goals of CLAS:
So here I will talk about C.L.A.S. (Character, Logic, Actions, State), the flexible design pattern for video game AI that I came up with and use. The main goal of this pattern is to make developing and maintaining complex AI for video games an easier, simpler, and faster, thing to do. It achieves that by applying two popular design principles:

1) By applying the design principle of Separation of Concerns, to divide the AI system to individual components in a way so the system is modular and makes sense.
2) To further reduce complexity by applying the KISS principle. This is done by minimizing the use of individual classes and inheritance. 

The architecture of CLAS:
CLAS applies the software design principle of SoC, by dividing the AI system to four distinct components:




1) Character: This component contains all the data that shape who the particular AI agent is, and what's his/her status. Things like the maximum movement speed, the current and max health points, specific behavior patterns etc that shape up the character's well... character, are set on this component. Imagine typical Character Sheets of pen and paper RPGs, in a digital form. In fact, this is how I came up with it, as I was developing an RPG and I was looking at the old traditional non-digital RPG games to start from scratch.

2) State: This component's job is to let the AI agent know some things about the state of the world. It deals with triggers, raycasting, and such stuff to let the AI agent know things such as "Am I in an area with toxic gas ?", "Do I have a direct line of sight with the player ?", "Am I on fire ?" etc.

3) Logic: This component has a method running each frame. I personally implemented in it a kind of Behavior Tree, by having a method that runs each frame with a bunch of if/else/elif statements, that call even more methods with if/else/elif statements that also lie on the same component. But you can go on a more GOAP style approach and use weights if you want. The purpose of this component is to decide what the individual AI Agent should do given the current state of the world provided by the State component, and the specific character of the AI agent, provided by the Character component. So each AI agent decides how it should respond dynamically given who it is, and what's the situation it's on.

4) Actions: This is a pool where all the individual methods of actions are. Methods like "ApproachTarget", "ShootTarget", "LookForAmmo" etc. The Logic component calls methods from this component. Not all AI agents are going to use all the actions in the Actions component, but it is good to have all different actions an AI agent can take in a single place.


Summary:
Each AI agent carries the exact same versions of the State, Logic, and Action components. You customize the agent by changing values on the Character component, and the rest of the components do the rest of the job. If you want to create new actions or variables that will let AIs know more of what's happening, you do it in on the corresponding components, so it's easy for all different AIs to access the new stuff. You also skip inheritance in the process. Since you customize each agent on the Character component, and the world state data, and actions are available individually to all actors, you can get away by changing values in the Character component, and then make prefabs of agents with different values instead of building a new class for each different character type.


The practical benefits of using CLAS:
So with this design pattern each AI agent has a copy of each of these 4 components. Here are some of the benefits you will get by implementing this pattern:


1) Debugging will become a lot easier, because if there's a problem you will know where to look for it. You can track down bugs easier. If there is a problem with collisions or raycasts, you know you have to look on State. If the AI does an action it shouldn't do given the circumstances, it's a problem you have to fix on the Logic component, and so on.
2) Adding or changing actions, logic, or things you want the AI to know about its surroundings will be easier. Because everything is nicely organized and separated.
3) Editing and creating new variations of enemy types / characters, also becomes easier. Instead of having numerous different classes you have to maintain, you only have a limited number of them, no matter the amount of different character / enemy types you want in your game. In many cases you will only have to change some values in the Character component if you want to add a new enemy type.

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου