unity AI之有限状态机
有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
状态机并不是一种算法,而是一种设计模式--状态模式
状态模式(state),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当前控制一个对象状态转换的条件表达式过于复杂的情况。把状态判断逻辑转移到表示不同状态的一系列类中,可以把复杂的逻辑简化。如果状态判断很简单,那就没必要使用状态模式。说白了,状态模式的目的是为了消除庞大的条件分支语句。通过把各种状态转移逻辑分布到state的子类之间,来减少相互之间的依赖。
总结得,实现有限状态机有几种方法:
第一种:面向过程的方式
if(...){...} else if(...){...}
这种方法适合简单的状态的转换;比如塔防游戏中,防御塔的状态,进入防御塔射程范围就射你,离开射程范围就待机。代码栗子:
float distance = 2f;// 敌人视觉范围
Quaternion origin;// 敌人初始方向
public Transform player;// 假设是玩家
float dis; // 敌人与玩家之间的距离
public GameObject bullet;// 子弹
void Start()
{
origin = transform.rotation;
}
void Update()
{
// 勾股定理计算敌人与玩家之间的距离
// Mathf API介绍:http://blog.csdn.net/ilypl/article/details/78466051
dis = Mathf.Sqrt(Mathf.Pow((transform.position.x - player.position.x), 2) + Mathf.Pow((transform.position.y - player.position.y), 2));
if (dis < distance)
{
transform.LookAt(player);
Instantiate(bullet, transform.position, transform.rotation);
}
else if(dis > distance)
{
transform.rotation = origin;
}
}
效果图:
例子源码:https://gitee.com/CCHChenChangHong/unityDeAI/tree/master/%E9%99%88%E5%B8%B8%E9%B8%BF%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA%E5%8D%9A%E5%AE%A2%E9%85%8D%E5%A5%97%E4%BB%A3%E7%A0%81/%E7%AC%AC%E4%B8%80part
第二种方法:枚举加switch
switch(...){case ...:...break;...}
这种方法基本适应大多数游戏,以格斗游戏为例,格斗游戏中有大量的动作元素,跑动,跳,蹲等
// 四种状态
public enum Status
{
Sleep,
Attack,
Walk,
Eat,
}
private Status status = Status.Walk;// 默认为Walk状态
public void Changestatus(Status status)
{
switch(status)
{
case Status.Sleep:
sleep();
break;
case Status.Attack:
attack();
break;
case Status.Walk:
walk();
break;
case Status.Eat:
eat();
break;
}
}
void Update () {
Status a = status;// 在Update中检测输入即可
Changestatus(a);
}
// 四种状态相对应的行为
void sleep(){ }
void attack(){ }
void walk() { }
void eat() { }
第三种为状态模式状态机:
同样以上面四种行为为栗子;
先定义一个抽象的方法:
public abstract class State
{
public abstract void Status(Do do);
}
Walk状态类
public calss WalkState:State
{
public override void Status(Do do)
{//walk的行为}
}
Attack状态类
public calss AttackState:State
{
public override void Status(Do do)
{//Attack的行为}
}
以此类推...
最后实现Do类:
public class Do
{
private State current;
public Do()
{
current = new WalkState();//初始化为Walk状态
}
public double change;//改变状态的条件,数据类型看具体情况
}
状态模式很容易扩展,只要把行为在行为类中修改就好了,不影响其他行为。
惯例给出我的微信公众号:
不管你关不关注,我都会在AI这条路上越行越远