Unity+4.x+Game+AI+programming CookBook 杂记

Chapter 1 Introduction to AI

AI in games游戏AI目的,创建难度适中的NPCs AI,尽量简化计算过程。

 

AI techniques

(1)       Finite State Machines(FSM):有限状态机

简单射击游戏敌人状态机

简单有限状态机的基本4组件:

1.状态(States):一系列游戏实体状态或者NPC可选择的状态(例如图中的Patrol(巡逻) Chase(追踪)Shoot(射击)。

2.过渡(Transitions):定义不同状态间的关系。

3.规则(Rules):触发过渡(如图player on sight, close enough to attack, and lost/killed player)

4.事件(Events):触发规则检查。(guard's visible area, distance with the player, and so on)

 

a monster in Quake 2(雷神之锤,没玩过- - 可能有如下状态:standing, waliking, running, dodging(闪避), attacking, idle, and searching

 

通常用if/else switch 可以轻易实现简单的状态机。

 

2Random and probability in AI:随机概率。

3The sensor system 感应系统。

       Position of the plyaer(玩家位置):选择攻击,追踪,搜寻。

       Buildings and objects nearby(附近的建筑和物体):隐藏或躲避。

       Player’s health and its own health(玩家和自身血量):选择撤退或前进。

       Location of resources on the map in an RTS game:选择占领或收集资源,需要创建和生产其他单位。

 

方法:

1Polling:轮询。

       FixedUpdate中使用if/else or switch 检查AI 需要的信息。

2The messaging system:消息系统。

       一个对象拥有监听器listener来监听消息系统发来的消息,从而进行一系统列处理。通常 消息与轮询一起使用。当AI接收到事件时,使用轮询检查更多细节。

 

Flocking swarming and herding 群体AI

       Separation:间距。维持最小间距

       Alignment:排列方式

       Cohesioin:中心

Path following and steering:路径跟踪导航

Hierarchy of motion behaviors 动作行为层级。

 

Such behaviors include seek and

flee, pursue and evade, wander, arrival, obstacle avoidance, wall following, and

path following

 

A* pathfinding A*搜寻

F = G + H

G and H, where G is the cost of movement from starting tile to current tile,

and H is the cost to reach the target tile from current tile.

G代表开始方格到当前方格的最短距离

H代表当前方格到目标方格的最短距离

 Calculating G G于格子左下角

 

 Calculating H H于格子右下角,既到目标最短距离。

 

 

 F于格子左上角

Frist 计算开始点(图中浅绿色格子)相邻的FGH,先选取F值最小的

 

 

Second 计算新的点图(F=4处)相邻FGH,因都为6任选,此处选取如图红色方框高亮格子

 

 

Third 计算得新的开始点周围绕的新格F值为8,则6<8,从下一个F=6的格子开始计算。

 

 

重复以上步骤,最终得到上图。最终路径可能为图中黄色格子

 

The behavior trees 行为树

tasks

Selector task

 

Sequence tasks

 

Chapter 2 Finite State Machines

The PlayerTankController Class

The bullet Class

Setting up waypoints

The abstract FSM class

The enemy tank AI

 

Using an FSM framework//有限状态机框架

(1) Transition:过渡enum

(2)StateID:状态ID enum

(3)FSMState:状态基类,abstract抽象类

Dictionary KEYTransitionVALUEtateIDmap

StateID 状态ID

       增删过渡

       获取过渡后的状态ID

       过渡原因函数

       行动函数

(4)FSMSystem:整个状态机系统

       状态表

       当前状态和ID

       构造函数:初始化状态表

       增删状态

       执行过渡。

(5)具体NPC控制类:NPCController

       设置过渡函数

 

Chapter3Random And Probability 随机概率

Character Personality

FSM with probability

FSM using probability

 

    利用数组构建状态池, 按状态池中状态比例计算结果。

Dynamic AI

 The Flow Channel

 

 

Chapter4Implementing Sensors

Aspect enum aspect 面貌 ,指物体的类别如player,enemy

Sense 感官基类: Aspect, 检测频率/距离,检测计时器, 虚函数初始化/更新

PerspectiveScense   透视(视野),是否在物体的视野内。

Touch 触摸,当其他物体进入碰撞区域。

总结:We can use the sensory system in combination with a behavior system to execute certain

behaviors for certain senses.

For example, we can use an FSM to change to chase and attack states from the patrol state once we have detected that there's an enemy within the line-of-sight

 

 

 

 

Chapter5 Flocking

Boid:术语类似鸟群的集群

Flocking algorithm 鸟群算法

Base

(1)Flock:跟随领头鸟

    (2)FlockController:领头鸟确定方向,地点

 

Chapter6PathFollowing and steer behavior

Following a Path

       Path:空物体,记录路径点

       PathFollow:沿路径点移动

Avoiding Obstacles

简单方法:用射线简单检测前方一定距离的障碍物。如果有障碍物,重新选择方向,使用原方向的法向量。

Chapter7A*pathfinding

循环函数使用Debug.log要小心。

NodeIcomparable

public float noteTotalCost;//G

       public float estimatedCost;//F

       public bool bObastacle;

       public Node parent;

       public Vector3 position;

       实现CompareTo 比较函数.

       MakeAsObstacle

       Other you like to add …..

PriorityQueue

Node ArrayList

Contains

First

PUSH:这里sort,易于查找最优路径

POP:这里sort

GridManager

       单例模式

       行数,列数,单元格子Sizebool showGrid, showObstacleBlocks,初始位置,obstacle数组。 Node二维数组

       Awake(): 初始化obstacle数组,初始位置,CalculateObstacles(计算障碍物的节点和初始化节点表)。

       CalculateObstacles(): 初始化所有节点表,标记障碍物

public Vector3 GetGridCellCenter (int index)

public Vector3 GetGridCellPosition(int index)

public int GetGridIndex(Vector3 pos)

public bool IsInBounds(Vector3 pos)

public int GetRow(int index)

public int GetColumn(int index)

public void GetNeighbours(Node node, ArrayList neighbors)

void AssignNeighbour(int row, int column, ArrayList neighbors)

void OnDrawGizmos()

public void DebugDrawGrid(Vector3 origin, int numRows, int numCols, float gridCellSize, Color color)

 

 

Astar

public class AStar : MonoBehaviour

{

       private static PriorityQueue closedList, openList;//优先列表:已访问列表, 未访问列表

 

       private static float HeuristicEstimateCost (Node curNode, Node goalNode)//计算估值H

       {

              Vector3 vecCost = curNode.position - goalNode.position;

              return vecCost.magnitude;

       }

 

       public static ArrayList FindPath (Node start, Node goal)//寻找路径算法:起点,终点

       {

              openList = new PriorityQueue ();//初始化未访问列表

              openList.Push (start);//将初始点Push

              start.noteTotalCost = 0.0f;//G = 0

              start.estimatedCost = HeuristicEstimateCost (start, goal);//H = dis<s,g>

 

              closedList = new PriorityQueue ();//初始化已访问列表

              Node node = null;

              while (openList.Length != 0) {//如果未访问列表有值

                     node = openList.First ();

                     if (node.position == goal.position) {//如果当前节点就是终点节点

                            return CalculatePath (node);//计算路径,返回路径List

                     }

                     ArrayList neighbours = new ArrayList ();//数组列表 邻近

                     GridManager.instance.GetNeighbours (node, neighbours);//获取当前节点的邻近

                     for (int i = 0; i < neighbours.Count; i++) {//遍历邻近表

                            Node neighbourNode = (Node)neighbours [i];

 

                            if (!closedList.Contains (neighbourNode)) {//如果已访问列表不存在此邻近节点

                                   float cost = HeuristicEstimateCost (node, neighbourNode);//计算邻近节点到此节点距离

                                   float totalCost = node.noteTotalCost + cost;//计算邻近节点的G

                                   float neighbourNodeEstCost = HeuristicEstimateCost (neighbourNode, goal);//计算邻近节点的H

                                   neighbourNode.noteTotalCost = totalCost;//G

                                   neighbourNode.parent = node;//邻近节点的父节点为此节点

                                   neighbourNode.estimatedCost = totalCost + neighbourNodeEstCost;//F

                                   if (!openList.Contains (neighbourNode)) {//如果未访问列表不存在此邻近节点

                                          openList.Push (neighbourNode);//压入

                                   }

                            }

                     }

                     closedList.Push (node);//此节点压入已访问列表

                     openList.Remove (node);//未访问列表移除此节点

              }

              if (node.position != goal.position) {//当所有可访问的节点都访问完的时候.

                     Debug.LogError ("Goal Not Found");

                     return null;

              }

              return CalculatePath (node);

       }

 

       private static ArrayList CalculatePath (Node node)

       {

              ArrayList list = new ArrayList ();

              while (node != null) {

                     list.Add (node);

                     node = node.parent;

              }

              list.Reverse ();

              return list;

       }

}

 

 

Chapter8 NavMesh

posted on 2013-11-21 20:47  鱼 丸  阅读(604)  评论(0编辑  收藏  举报