游戲人工智能開發(fā)之6種決策方法

轉自:http://www.gameres.com/467913.html

人工智能遵循著:感知->思考->行動

決策方法:有限狀態(tài)機(Finite-State Machines)活鹰,分層狀態(tài)機(Hierarchical Finite-State Machines),行為樹(Behavior Trees)澈侠,效用系統(Utility Systems)拴孤,目標導向型行動計劃(Goal-Oriented Action Planners)弊决,分層任務網絡(Hierarchical Task Networks)

1.有限狀態(tài)機

有限狀態(tài)機是目前游戲AI中最常見的行為模型危融。狀態(tài)機的代碼簡單又快速陵刹,使用上強大啃洋、靈活、計算開銷小遍希。

狀態(tài)機的一個好處是可以可視化等曼,如下圖所示:



圖中有四個狀態(tài):巡邏(patrol),查看(investigate)凿蒜,攻擊(attack)禁谦,逃走(flee),我們把實心圓當做初始狀態(tài)废封。

簡要過程:假設NPC士兵正在保衛(wèi)他的陣地州泊,當前狀態(tài)為巡邏,當他聽到什么動靜時就會轉到查看狀態(tài)漂洋,跑到聲音源去查看遥皂,如果看到敵人就轉到攻擊狀態(tài),如果沒看到過一段時間又會回到巡邏狀態(tài)刽漂。在攻擊狀態(tài)中如果血值低下就會進入逃跑狀態(tài)演训。如果擊敗了敵人,又會回到巡邏狀態(tài)贝咙。

狀態(tài)機狀態(tài)類的一個主要結構如下样悟,onEnter函數就相當于unity中的Start()函數,在類開始時調用庭猩,作為對舊狀態(tài)的過度和新狀態(tài)產生的開始窟她,比如當從巡邏轉向攻擊狀態(tài)時,可以在攻擊狀態(tài)的開始讓NPC大喊“發(fā)現敵人蔼水!進攻震糖!”等等。onUpdate()就相當于unity中的Update(),你可以讓它每幀都執(zhí)行趴腋,或者幾秒鐘執(zhí)行一次吊说,是循環(huán)執(zhí)行的,每次執(zhí)行時間間隔由你來決定优炬。onExit()就是在退出一個狀態(tài)之前要執(zhí)行的疏叨,比如,殺死敵人之后由攻擊狀態(tài)轉向巡邏狀態(tài)之前穿剖,讓NPC做一個歡呼手勢并大叫勝利了。FSMTransition列表為將要轉到的所有可能的狀態(tài)卦溢。

class FSMState
{
  virtual void onEnter();
  virtual void onUpdate();
  virtual void onExit();
  list<FSMTransition> transitions;
};

每個狀態(tài)還存儲著FSMTransition的類糊余,代表能從當前狀態(tài)可以轉到的狀態(tài)

class FSMTransition
{
  virtual bool isValid();
  virtual FSMState* getNextState();
  virtual void onTransition();
}```
 當轉換條件滿足時isValid()返回true秀又,比如當發(fā)現敵人NPC就從巡邏狀態(tài)轉到攻擊,getNextState()返回將要轉到的狀態(tài)贬芥,onTransition()是狀態(tài)之間轉換的過渡吐辙,和上面說的onEnter()差不多。

  最后是有限狀態(tài)機類FiniteStateMachine

class FiniteStateMachine
{
void update();
list<FSMState> states;
FSMState* initialState;
FSMState* activeState;
}

有限狀態(tài)機類包含一個包含所有狀態(tài)的列表states蘸劈,initialState為初始狀態(tài)昏苏,activeState為當前狀態(tài)。

  偽代碼如下:
在  activeState.transtitions中循環(huán)調用isValid()威沫,檢測是否符合達到下一狀態(tài)的條件
如果符合轉換條件
  調用activeState.on Exit()贤惯,退出當前狀態(tài)
  設置activeState 為 validTransition.getNextState(),把當前狀態(tài)賦值為下一狀態(tài)
  調用activeState.onEnter()棒掠,下一狀態(tài)的開始
如果不符合轉換條件孵构,調用activeState.onUpdate(),讓NPC執(zhí)行當前狀態(tài)需要做的事
在編寫有限狀態(tài)機的代碼只前最好畫一個上面的草圖烟很,這樣既可以明確轉換關系颈墅,又可以不漏掉該有的狀態(tài)。
###分層有限狀態(tài)機

  有限狀態(tài)機雖然好雾袱,但是它有很大的缺點恤筛,當狀態(tài)少的時候可以運用自如,當狀態(tài)多的時候10個以上就已經結構非常復雜芹橡,而且容易出錯毒坛。

  如果我們讓NPC巡邏兩個地方,比如安全的室內僻族,和門口粘驰。
![](http://upload-images.jianshu.io/upload_images/3962099-3fde45f17bd53bd1.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如果我們想在一個狀態(tài)上附加一些狀況,例如當NPC在巡邏時述么,讓他接一個電話然后再恢復巡邏蝌数,此時如果使用有限狀態(tài)機的話我們必須要新建一個打電話的狀態(tài)來做過渡,但是此時的巡邏有兩個度秘,所以能接到電話的狀態(tài)也有兩個顶伞,然后加了兩個相同的狀態(tài),很多這樣的重復的小狀態(tài)使得狀態(tài)機越來越復雜剑梳。如下圖:
![](http://upload-images.jianshu.io/upload_images/3962099-ce1106a17c7118c9.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
這時唆貌,我們可以用分層有限狀態(tài)機來解決這個問題,把多個狀態(tài)機歸為一層垢乙,如下圖锨咙,把巡邏安全處和門口歸為看守建筑,這樣我們只需要有一個打電話狀態(tài)就可以了追逮。
![](http://upload-images.jianshu.io/upload_images/3962099-c93900f0bda0e2b8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
分層有限狀態(tài)機增加了一個滯后酪刀,在有限狀態(tài)機中并沒有粹舵,在一個普通的有限狀態(tài)機中,是從初始狀態(tài)開始的骂倘,在分層有限狀態(tài)機中是一個嵌套的狀態(tài)眼滤。注意上圖有H的圈,代表歷史狀態(tài)(history state)历涝,當我們第一次進入嵌套狀態(tài)->看守建筑時诅需,歷史狀態(tài)H表示為初始狀態(tài),之后歷史狀態(tài)H表示為最近處在的一個狀態(tài)荧库。

  在我們的例子中:初始狀態(tài)就是看守建筑堰塌,,然后進入看到手機按住這個嵌套电爹,巡邏安全處是初始狀態(tài)蔫仙。當從巡邏安全處轉換到巡邏門口這個狀態(tài)時,H歷史狀態(tài)就轉變?yōu)檠策夐T口狀態(tài)丐箩,此時來電話了摇邦,轉換到接電話狀態(tài),接電話結束屎勘,我們回到嵌套狀態(tài)中的歷史狀態(tài)施籍,此時為巡邏門口,可見H歷史狀態(tài)就是一個臨時的概漱,便于嵌套外的狀態(tài)返回到之前的嵌套內的小狀態(tài)丑慎,以不至于出錯,或者換回了別的狀態(tài)瓤摧,如果接完電話回到巡邏安全處竿裂,那就出大錯了。

  分層有限狀態(tài)機照弥,就這樣避免了重復狀態(tài)腻异,可以實現更大的更復雜的狀態(tài)。

  實例:

  Halo2使用了這一技術这揣,如下圖:
![](http://upload-images.jianshu.io/upload_images/3962099-d22955352723ff8e.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可見:把使用手雷悔常、掩蔽、防御歸為自衛(wèi)给赞,交戰(zhàn)部分使用了多層嵌套机打,但是原理是一樣的,向尸體設計和搜查尸體歸為戰(zhàn)后處理片迅。在撤退和閑置部分只有一個行為被嵌套残邀,但是日后可以繼續(xù)添加行為,可擴展性良好。

  至于如何在嵌套的層里對行為進行選擇罐旗,可以就按這個順序執(zhí)行膳汪,也可以加上權重優(yōu)先級,或者你想讓他執(zhí)行哪個通過代碼來控制九秀。

###行為樹

  行為樹是樹型結構的,每個節(jié)點都代表了一個行為粘我,每個行為都可以有子行為鼓蜒。

  所有行為都有一個先決條件,就是產生的這些行為的條件征字。

  整個算法先從樹的根部開始都弹,然后開始檢查每一個先決條件。樹的每一層只可以執(zhí)行一個行為匙姜,所以當一個行為正在執(zhí)行畅厢,它的兄弟節(jié)點都不會被檢查,但是它們的子節(jié)點還是要檢查的氮昧。相反如果一個行為的先決條件當前并不滿足框杜,則跳過判斷它的子節(jié)點,繼續(xù)判斷它的兄弟節(jié)點袖肥。一個樹全部檢查完畢之后咪辱,決定執(zhí)行優(yōu)先級最大的,然后再依次執(zhí)行每個動作椎组。

  偽代碼:

使根節(jié)點為當前節(jié)點
當存在當前節(jié)點
  判斷當前節(jié)點的先決條件
  如果先決條件返回true
    把節(jié)點加到執(zhí)行清單
    使子節(jié)點為當前節(jié)點
  否則
    使兄弟節(jié)點為當前節(jié)點
執(zhí)行執(zhí)行清單上的所有行為

不同于狀態(tài)機油狂,行為樹是無狀態(tài)的,不需要記下之前執(zhí)行的行為寸癌,只是判斷行為該不該執(zhí)行专筷。

  行為樹的節(jié)點之間是不相關的,刪除或增加節(jié)點蒸苇,對其他節(jié)點都無影響磷蛹。所以,可擴展性也是行為樹的一個優(yōu)勢填渠。另外還可以為決策樹添加靈活性與隨機性弦聂,父節(jié)點可以隨機決定是否檢查子節(jié)點。

  缺點:決策樹做的選擇并不一定是最優(yōu)的氛什,結果也不一定是我們想要的莺葫。而且決策每次都要從根部往下判斷選擇行為節(jié)點,比狀態(tài)機要耗費時間枪眉。每次決策都要經過大量的條件判斷語句捺檬,會變得非常慢。

  另外還有一個問題贸铜,例如:一個農民要收割作物堡纬,敵人出現了聂受,農民逃跑,逃出了距離敵人的一定范圍之后烤镐,又回去收割作物蛋济,走到敵人的范圍又逃出,這樣來回往復炮叶,是一個弊端碗旅,,可以根據情況來寫代碼避免镜悉,否則會被玩家***的祟辟。

###效用系統

  人工智能的邏輯->電腦的邏輯,是基于簡單的bool問題侣肄,比如:“我能看到敵人嗎旧困?”,“我有彈藥嗎”稼锅,是簡單的是或者不是的問題吼具,所以做出的行為通常是極端化的,一個單一的行動缰贝。比如:

if (CanSeeEnemy())
{
AttackEnemy();
}
if (OutOfAmmo())
{
Reload();
}
即時有多條件的行為馍悟,bool判斷帶來的也是一個單一的行動。
if (OutOfAmmo() && CanSeeEnemy())
{
Hide();
}```

所以有些情況剩晴,只是做這些布爾判斷是不合適的锣咒,會遺漏很多情況,判斷也不妥當赞弥。比如:我們可能需要同時考慮與敵人的距離毅整、有多少彈藥、饑餓程度绽左、HP值悼嫉,等等。這些判斷條件能映射出許多動作拼窥,比我們單一的判斷做不做這個動作要好很多戏蔑。utility-based system,基于效用的系統鲁纠,會根據權重总棵、比率、隊列和許多需要考慮的事項來做出最優(yōu)選擇改含,使AI比普通的行為樹更有頭腦情龄。根據上面的例子,使用效用系統我們的AI可以做出我們想要的動作,并根據當前情況做出不同強度的動作骤视,使AI真實鞍爱、更具可能性,也不再是只有一個正確的選擇了专酗。決策樹就是對AI說睹逃,“只是你將要做的一個行為”,效用系統就是對AI說:“這些是你可能要做的行為”

Sims模擬人生的人工智能就是使用的效用系統(sims的人工智能讓我膜拜至今)祷肯,在sims中唯卖,小人結合當前環(huán)境和自身的狀態(tài),來做出行動的選擇躬柬。例如:小人“非常餓”結合環(huán)境“沒有食物”會比只有“有一點餓”更加吸引人的眼球。如果“有一點餓”小人會以接近“美食”為第一執(zhí)行行為抽减。注意允青,這里的“美食(的美味程度)”、“食物很少(食物儲備程度)”卵沉、“一點餓(餓的程度)”颠锉,都是一個有范圍的數值(常用的是0-1的浮點值)。

當需要選擇新的行為時史汗,我們通過分數(上面說的各種程度)來選擇相對最優(yōu)的選擇琼掠,或者加上一個隨機值再選擇,使得接近優(yōu)選的幾個選擇都有一定幾率(幾率可根據所加隨機值決定)被選中停撞。

目標導向型行動計劃

GOAP來源于STRIPS方法瓷蛙,這兩種都是讓AI創(chuàng)造他們自己的方法去解決問題,我們提供給它一系列可能的動作作為對這個世界的描述戈毒,和每個動作使用的先決條件艰猬,和行動帶來的影響。AI擁有一個初始狀態(tài)和他需要達到的目標埋市。有一組目標冠桃,AI可以通過優(yōu)先級或當前狀態(tài)選擇一個。計劃系統決定一個動作序列來滿足當前目標道宅,計劃出一個像路徑一樣的能最簡單達到目標狀態(tài)的動作序列食听。

GOAP是一個反向鏈接搜索,從要實現的目標開始污茵,找到什么動作能實現目標樱报,在尋找剛才動作的先決條件,一直往前推省咨,知道達到你的當前(初始)狀態(tài)肃弟。這種反向鏈接搜索替代了啟發(fā)式的前向鏈接搜索。

偽代碼:

把目標加到未解決事件列表
對于每個為解決事件(for)
  移除這個為解決事件
  找到達成事件的動作
  如果動作的先決條件已經滿足
    增加動作到計劃中
    往回推需要達到先決條件的動作到計劃中
  否則
    添加該先決條件到未解決時間中

例如:我們建立一個NPC士兵,把它的目標設為殺死其他敵人笤受,我們設置它的目標為Target.Dead穷缤。為了讓目標去死,NPC必須要有一個武器用來射擊箩兽,這是一個先決條件津肛,但是現在NPC并沒有正在裝備的武器,NPC就需要執(zhí)行找到武器這個動作汗贫,如果NPC有武器庫身坐,他就會從武器庫中拿一個,如果病沒有武器庫落包,就需要尋路去找一個武器裝備了部蛇。得到武器裝備之后就要找到敵人,實現方式多種多樣咐蝇,徒步尋找涯鲁、或者NPC周圍有車也可以開著車去尋找。我么發(fā)現有序,我們給NPC大量的動作選擇抹腿,讓NPC自己決定該做什么,因而產生動態(tài)不可預知又有趣的行為旭寿,而且表現得很自然警绩,比開發(fā)者創(chuàng)建行為好多了。

分層任務網絡

HTN也是尋找一個計劃來讓AI執(zhí)行盅称,不同之處在于怎樣找出這個計劃肩祥。開始擁有一個初始狀態(tài)和一個跟任務代表我們需要解決的問題。原理是最高級的任務分解成更小的任務再繼續(xù)分解直到我們解決問題微渠。每個高級任務都有很多方式被完成搭幻,當前世界狀態(tài)決定高級任務要分解成哪組小任務。HTN與GOAP相反逞盆,HTN是前向鏈接搜索檀蹋,是從當前狀態(tài)一直推到目標狀態(tài),向前推直到問題解決云芦。世界狀態(tài)分散成幾種屬性俯逾,它的HP、精力舅逸,敵人的HP桌肴、相距距離,計劃根據這些來制定琉历。

我們有兩種任務:原始任務和復合任務坠七。原始任務是可以只解決問題的任務水醋,也就是可以直接達到目標的任務。在游戲中彪置,它可以為開火拄踪、裝填子彈、移動到掩蔽物拳魁。這些人物可以影響世界狀態(tài)惶桐,開火這個任務需要先有子彈,并執(zhí)行裝填子彈這個任務潘懊。復合任務是高級別的任務姚糊,可以看作方法。一個方法是一組任務可以完成復合任務授舟,這一組任務是由先決條件決定的救恨。復合任務讓HTN推斷出世界并且決定該做什么動作。

使用復合任務释树,我們就能構建一個HTN域忿薇,這個域是一大層任務,代表我們解決問題的方法躏哩。

偽代碼:

增加根復合任務到分解列表中
對于每個在我們分解列表中的任務(for)
  移除任務
  如果任務是復合任務
    找到滿足當前條件狀態(tài)并且能處理該復合任務的方法
    如果該方法找到了,增加方法的任務到分解列表中
    如果沒找到揉燃,恢復到之前分解任務的狀態(tài)中
  如果任務是原始任務
    在當前狀態(tài)下執(zhí)行任務
    增加任務到最終計劃列表```
HTN就是從最高級的根任務分解更小的任務再分解成更更小扫尺,分解是需要判斷當前狀態(tài)和條件的。當我們終于分解為原始任務炊汤,我們把原始任務加到最終計劃中正驻,每一個原始任務都是一個可操作步驟,我們可以直接執(zhí)行它抢腐。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末姑曙,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子迈倍,更是在濱河造成了極大的恐慌伤靠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啼染,死亡現場離奇詭異宴合,居然都是意外死亡,警方通過查閱死者的電腦和手機迹鹅,發(fā)現死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門卦洽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斜棚,你說我怎么就攤上這事阀蒂「么埃” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵蚤霞,是天一觀的道長酗失。 經常有香客問我,道長争便,這世上最難降的妖魔是什么级零? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮滞乙,結果婚禮上奏纪,老公的妹妹穿的比我還像新娘。我一直安慰自己斩启,他們只是感情好序调,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兔簇,像睡著了一般发绢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上垄琐,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天边酒,我揣著相機與錄音,去河邊找鬼狸窘。 笑死墩朦,一個胖子當著我的面吹牛,可吹牛的內容都是我干的翻擒。 我是一名探鬼主播氓涣,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陋气!你這毒婦竟也來了劳吠?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤巩趁,失蹤者是張志新(化名)和其女友劉穎痒玩,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體议慰,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡凰荚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了褒脯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片便瑟。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖番川,靈堂內的尸體忽然破棺而出到涂,到底是詐尸還是另有隱情脊框,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布践啄,位于F島的核電站浇雹,受9級特大地震影響,放射性物質發(fā)生泄漏屿讽。R本人自食惡果不足惜昭灵,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伐谈。 院中可真熱鬧烂完,春花似錦、人聲如沸诵棵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽履澳。三九已至嘶窄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間距贷,已是汗流浹背柄冲。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忠蝗,地道東北人羊初。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像什湘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晦攒,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容