Hello
Ive been programming for the past 3 years in C# inside unity, until now I thought my AI skills were acceptable and able to achieve every goal I have needed, but I many times get into situations that makes it diffcult to handle many states of an AI.
I did not follow any article or a tutorial, I just came up with a solution that I thought was good enough.
What I would really appriciate, is if you could judge my way of making AI. Im not familiar with other ways, and I dont know if my way is good enough. Or if you know of a good source that teaches a way of creating a good AI, please post it here ![]()
This is how I currently program any AI:
1. I get a list of every state this AI can be, lets say it can:
a. Idle
b. Walk
c. Chase an entity
d. Attack
e. Get hit
f. Die
2. I find out how to link each of the states to another state(s), causing evey state to go to another eventually:
Idle ā Walk (When a random time (4 ~ 20) has passed)
Idle ā Chase an entity (When an entity is close enough (10 units) and can be seen)
Chase an entity ā Attack (When the entity is close enough (1 unit) and can be attacked)
Chase an entity ā Idle (When an entity is unchaseable (too far, cannot be seen or dead))
⦠and so on ā¦
3. I write a coroutine for each of these states, linking every coroutine to another just like I have wrote.
private IEnumerator IdleRoutine()
{
float startTime = Time.time;
float randomTime = Random.Range(4, 21);
do
{
// Check for an entity to chase. if found, chase it
Entity entity = FindEntityToChase();
if(entity != null)
{
// Start the chase entity state.
StartCoroutine(ChaseEntityRoutine(entity));
// Leave this state.
yield break;
}
yield return null;
}
while(Time.time < startTime + randomTime);
// Code here initiated when the random time has passed, Starting the walk state:
StartCoroutine(WalkRoutine());
}
This is something I just wrote, I didnt completed everything since I dont want this to take too much space, but I hope many of you get the idea.
The problems with my approach:
Take a second to think about the Get Hit state, it isnt linked to another state, instead, it is something which depends not on this script, but on the player script, or any other entity script (That can attack this AI).
The AI can not know when it will get hit, it can just wait until a player hits it.
This is one reason to be very careful, because when getting hit, you want to exit the current state you are in, you certently dont want to stay in the Idle state while you are getting hit⦠this will make an AI behave very badly, at any given point, an AI should only be on one state.
Unity lets you exit ALL coroutine at any time by calling the method: StopAllCoroutines(), but using this method has proven to be a bad idea, if not being careful.
Why? Lets say the AI is in a middle of a very important state, a state that changes the behaviour of many of its components and variables which are handled only by that state, like in the Attack state: In this state the AI instantiates an arrow, and aiming it to the player. when the AI gets hit, during this state, the arrow should be gone.
But when you get hit, you dont have any access to the coroutine currently on (the AttackRoutine in this example), you may stop it, but what about the arrow? you will need a reference to it, in order to destroy it, which isnt a hard thing to do, but sure can get hard to follow when having 20 states, or even 50 states the AI can be in.
The AI may have 20 different skills which each one of them creates a different object, changes values of the enemy like the speed, jump height⦠something you would like to reset when the state is over.
A run state which changes the speed to 30, get canceled because of the Get Hit state, if the speed value is not resetted, it will make the AI move at the speed of 30 instead of 20 when reaching the Walk state.
What I currently do to handle this issue, is to create a delegate which holds a āBreak Functionā to the state the AI is currently in.
What the break function does, is to āresetā the AI to the normal values after the current state has changed them, and whenever I call the function StopAllCoroutines(), I also make sure I Invoke the delegate referencing the break function.
Is this way of coding complex AI is the right way? If not, can you give me an example or tell me what to change with my way of coding AI?
Sorry about the long post S: but I really need to know, because my project im currently working on has a variety of complex AIās