# AI framework
## 1. Several AI designs
AI in the game a lot, but why do people always feel ai writing up very difficult, I later thought about it, the main reason is the use of improper methods. Before people write ai mainly have several options.
### a. State machine  
I do not know who came up with this approach, really powerless to complain. Originally any data on the object is the state, this method and to define some state into a new kind of node, the object on the state change will cause the conversion between nodes, the implementation of the corresponding method, such as OnEnter OnExit and so on. Here is an example of a monster, monsters can be divided into a variety of states, patrol, attack, chase, return. The state changes of the monster are:

Patrol->Chase Patrol state found a distant enemy to chase state  
Patrol->Attack Patrol find enemy can be attacked to attack state  
Attack->Chase The attack state finds an enemy in the distance and goes after it.  
Attack->Return Attack state find the enemy is too far to return state  
chase->return chase state found too far from the enemy to return to the state  

There are so many state transitions that it's hard to find out if I've missed them here. Once there are more nodes, any two nodes may need to be connected, and it will become a super complex mesh structure, the complexity is the square of N, and it is very difficult to maintain. In order to solve the problem of complex mesh structure and then upgraded to a hierarchical state machine and so on. Of course, various patching methods still do not solve the essential problem. It is not your problem to use bad state machines, it is the problem of state machines.

### b. Behavior tree
The ai of the behavior tree is responsive ai, the tree from top to bottom (or from left to right execution, here from top to bottom for example) is actually the action node ranked a priority, the action above the first to determine whether to meet the conditions, meet the implementation. We won't go into details here. The complexity of the behavior tree is N, greatly simplified than the state machine, but there are still many defects, ai too complex when the tree will become very large, and difficult to reconfigure. For example, in our own project, we want to make a robot ai similar to a human, automatically do tasks, fight monsters, play the system in the game, chat with people, and even attack others. Imagine how complex this tree will become! Another drawback of the behavior tree is that some action nodes are a persistent process, that is to say, a concurrent process, behavior tree management up concurrent process is not very good, such as the above example, need to move to the target side, this move is made into a concurrent process it, or every frame move it? This is a difficult problem, how to do it is not comfortable.

## 2. my approach
What is ai? Very simple, ai is constantly based on the current state, perform the appropriate behavior. Remember these two sentences, it is important, this is the essence of ai! These two sentences are divided into two parts, one is the state judgment, the second is the execution of behavior. State judgment is well understood, what is the behavior? Take the above example of the monster state machine, the behavior of the monster is Patrol, attack the enemy, return to the patrol point. For example.

Patrol (when the monster is within the patrol range, there is no enemy around, choose the next patrol point, move)  
attack the enemy (when the monster found within the guard range of the enemy, if the attack distance enough to attack, not enough to move over to attack)  
Return (when the monster found more than a certain distance from the birth point, plus the invincibility buff, move to the birth point, to the birth point, remove the invincibility buff)  

Unlike the state machine, these three state changes do not care about what the last state is, only about whether the current conditions are met, meet the implementation of the behavior. Behavior may be able to perform instantly, but also may be a continuous process, such as patrol, choose the next patrol point to move over, go to a point and then choose a point, and so on and so forth. For example, attacking the enemy, may need to move to the target to attack.

How to design this ai framework? Here it is very simple, abstract ai nodes, each node contains a conditional judgment, with the implementation of behavior. The behavior method should be a concurrent process
```csharp
public class AINode
{
	public virtual bool Check(Unit unit) // test whether the condition is met
	{		
	}

	public virtual ETTask Run(Unit unit)
	{		
	}
}
```
Thinking further, if the monster is on patrol and finds an enemy, then the monster should interrupt the current patrol and go on to perform the act of attacking the enemy instead. So our behavior should need to support being interrupted, which means that the behavior concurrent should support cancellation, and this is especially important to note that any concurrent in the behavior Run method should support the cancellation operation!
```csharp
public class AINode
{
	public virtual bool Check(Unit unit)
	{		
	}

	public virtual ETVoid Run(Unit unit, ETCancelToken cancelToken)
	{
	}
}
````

Implement three ai nodes XunLuoNode(patrol) GongjiNode(attack) FanHuiNode(return)

```csharp
public class XunLuoNode: AINode
{
	public virtual bool Check(Unit unit)
	{
		if (not in patrol range)
		{
			return false;
		}
		if (there are enemies around)
		{
			return false;
		}
		return true;
	}

	public virtual ETVoid Run(Unit unit, ETCancelToken cancelToken)
	{
		while (true)
		{
			Vector3 nextPoint = FindNextPoint();
			bool ret = await MoveToAsync(nextPoint, cancelToken); // move to the target point, return false means the process is canceled
			if (!ret)
			{
				return;
			}
			// stay for two seconds, note that any concurrent process must be able to be cancelled here
			Wait(2000, cancelToken). bool ret = await TimeComponent;
			if (!ret)
			{
				return;
			}
		}
	}
}
```
The same can be achieved for the other two nodes. It's not enough to design the nodes, you also need to string the nodes together so that the ai can rotate
```csharp
AINode[] aiNodes = {xunLuoNode, gongjiNode, fanHuiNode};
AINode current;
ETCancelToken cancelToken;
while(true)
{
	// Every second you need to re-determine if the new behavior is satisfied, this time can be set by yourself
	await TimeComponent.Instance.Wait(1000);

	AINode next;
	foreach(var node in aiNodes)
	{
		if (node.Check())
		{
			next = node;
			break;
		}
	}

	if (next == null)
	{
		continue;
	}

	// If the next node is the same as the current one, then it is not executed
	if (next == current)
	{
		continue;
	}

	// Stop the current concurrent process
	cancelToken.Cancel();

	// Execute the next concurrent process
	cancelToken = new ETCancelToken();
	next.Run(unit, cancelToken).Coroutine();
}
```
This code is very simple, meaning that it iterates through the nodes every second until it finds a node that satisfies the conditions and then executes it, waiting for the next second to determine, before executing the next node, interrupting the currently executing concurrent process.
A few misconceptions about the use:
1. behavior if there is a concurrent process must be able to cancel, and pass in cancelToken, otherwise something will go wrong, because once the monster meets the execution of the next node, you need to cancel the current concurrent process.
2. different from the behavior tree and state machine, the role of the node is only a piece of logic, the node does not need to share. Shared is the concurrent methods, such as MoveToAsync, monster patrol node can be used, the monster attack enemy node in pursuit of the enemy can also be used.
3. nodes can do very large, such as automatically do the task node, move to the npc, pick up the task, according to the task of subtasks to do subtasks, such as moving to the monster point to fight monsters, move to the collection of things to collect, etc., after doing all the subtasks, move to the task npc to turn in the task. All of this is written in a while loop, using a concurrent string.

Thinking about a big question, how do you design a piezo bot? What does a piezo bot need to do? Automatically do tasks, automatically play various systems, automatically attack enemies, will counterattack, will find people to chat, etc.. Just make an ai node for each of the above mentioned. Brothers, AI simple or not?



