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這條路上越行越遠