《The Last Of Us》的同伴AI(一):非戰鬥跟隨AI

《The Last Of Us》的同伴AI(一):非戰鬥跟隨AI

來自專欄兔四的遊戲攻略書96 人贊了文章

本文大部分內容都是翻譯自Max Dyckhoff在GDC 2014中的一篇演講,演講題目是《Ellie- Buddy AI In The Last Of Us》,從多個角度去向大家介紹了《最後生還者》中艾麗同伴AI的做法。

題目中的Buddy AI翻譯過來就是同伴AI,同伴AI在很多大作里都有出現,比如頑皮狗自家《神秘海域4》中的山姆·德雷克、《失落的遺產》中的Nadine、今年索尼《戰神》中的兒子阿特柔斯等等,在這些時刻陪伴在玩家旁邊的角色上使用的AI就是同伴AI。

同伴AI的作用不言而喻,同伴可以幫你戰鬥、可以跟你聊天、平時會在旁邊遊盪、玩家陷入謎題的時候又會提供幫助,同伴AI涉及的範圍相當之廣,而且根據玩家當前的行為會有不同的AI。而且在功能性之外,同伴AI也是用來刻畫人物性格的重要工具,合情合理的AI才能讓玩家代入到遊戲中去。

原演講的內容相對比較口語化,所以我會把核心內容整理翻譯之後,以可讀性比較高的描述方式寫出來,部分章節我會插入原演講的PPT截圖以方便閱讀、部分內容可能會加上我自己的一些理解。演講的文字量相當大,所以比較方便閱讀我會分成幾個章節來寫,有興趣的話還可以到原鏈接里去看:

演講的官方音頻鏈接:點我跳轉

演講的官方PPT鏈接:點我跳轉

演講的視頻有人搬到B站了:點我跳轉

目錄

第一章 同伴AI的設計思路(當前章節)

第二章 非戰鬥狀態下的跟隨AI(當前章節)

第三章 戰鬥狀態下的跟隨AI(點擊跳轉)

第四章 艾麗的戰鬥AI(點擊跳轉)

第五章 其它AI細節(點擊跳轉)

第六章 總結(點擊跳轉)

第一章 艾麗AI的設計思路

1 我們為什麼需要同伴AI

從很多方面來說,艾麗跟我們玩家是很非常非常像的。與喬爾不同,艾麗跟玩家一樣都是剛剛才開始接觸到這個充滿瘟疫的世界,艾麗跟玩家一樣會害怕那些感染者,艾麗厭惡戰爭,艾麗之前從未感受過這種末日世界裡人類還要互相殘殺的情景。至少對我而言,艾麗是一個充滿真實感的角色。

我們在創造艾麗這個角色的時候,有很多東西是需要避免的。在一些具有同伴AI的遊戲里,玩家經常感覺到自己要去保護同伴,需要時刻擔心同伴的安危,看他是不是被困住了、是否需要援助他。而我們不想這樣,我們反而希望艾麗是一個能幫助玩家的角色,艾麗不會令你覺得討厭、喬爾(玩家)也不會埋怨艾麗。總而言之,她是玩家真正的同伴,而不是玩家通關遊戲的累贅。

所以接下來,我會講到我們用怎樣的一個系統來創造艾麗的AI。當然我只會挑一些重點和基礎的設定來說,希望大家可以理解我們做這個AI系統的思路,然後去思考進一步的設計。

我們最初在2013年1月公布了《最後生還者》,並且給大家提供了大概20~30分鐘試玩版本。但經過那次測試我們發現,艾麗的同伴AI並達不到我們的預期。然後我們就決定延期遊戲的發售,我們額外花了五個月的時間去重做了AI

我們希望喬爾和艾麗在戰鬥中是互相協同、互相扶持的,我們希望戰鬥是更有情感衝擊力的。戰鬥中遇見的感染者會讓人害怕,但害怕的原因不僅僅是因為感染者在攻擊你(喬爾),還會因為你害怕你的朋友(艾麗)會遭到感染者的攻擊。我們希望你的同伴會至始至終都在任何遭遇中陪伴著你,這就是情感的表達方式之一。

在最初的版本里,上面說到的這些東西全部都是直接寫到角色的代碼里。但我們整個遊戲不可能只有一場戰鬥,喬爾和艾麗在後面還有經歷很多很多的事情。直到那時候我們才意識到,我們需要做一個同伴AI、用AI來應對大部分場合。雖然我們已經之前已經做了一些綜合性、能廣泛使用的AI,但那也不是我們最終想要的體驗,所以我決定重新回到起跑線,在距離發售還有5個月的時候重新開始做同伴AI。

但幸運的是我們足夠優秀的團隊,我們有非常出色的物理系統、運動系統、動作系統和尋路系統,所以同伴AI其實就是在這些基礎系統上額外做文章。

開始同伴AI的工作時,一般我們都會想到戰鬥AI,但我們想優先把位置關係AI做了.比如說艾麗會傾向於待在喬爾的旁邊、而非靠近那些可怕的感染者。只要完成了這個位置關係的AI,艾麗的同伴AI實際上已經會有明顯體驗了。

所以我開始重點關注艾麗跟喬爾之間的關係。我們想讓玩家感受到他們兩人之間是如何共同去應對困境,喬爾作為玩家控制的角色是如何去關心艾麗,之後艾麗又是如何反饋喬爾的幫助,艾麗如何回報喬爾等等。所以我跟Bruce(Max的同事)花了很長的時間去討論艾麗的之前的經歷、艾麗跟喬爾結識之後發生的一切、艾麗一直跟著喬爾走的原因等等。

2 艾麗AI的設計方向

我們想做的第一件事就是讓艾麗更靠近喬爾

這有很多很多的好處,如果讓艾麗遠離敵人的話會讓我們的敵人AI更難出錯,這個等下我們在後面的章節會講到;如果讓艾麗距離喬爾太遠、不主動靠近你、不跟你聊天,你可能會開始忘記她的存在,再加上我們的遊戲場景到處都是廢墟、被毀壞的建築、荒地,玩家可能就會有一種廢土中身陷孤獨的感受,這並不是我們所預期的遊戲體驗(畢竟頑皮狗不是在做輻射系列)。我們希望的是讓玩家保持對艾麗的關注,並且會想要照顧艾麗(畢竟艾麗設定的年齡跟喬爾的女兒相仿),同時也方便艾麗對喬爾進行交互。

第二點就是我們希望艾麗是有用的

艾麗應該不僅僅作為喬爾的一個保護對象,艾麗會在戰鬥中、或者一些解謎場景中會幫助喬爾。當然艾麗能夠做的事情有限,但艾麗會隨著遊戲進程的推進會越來越有用,至少她不會是一個累贅。

第三個方向就是我們想讓艾麗在戰鬥內外都會很有趣

我們為她製作了一套特殊的動畫,讓艾麗在戰鬥中和非戰鬥時間內都有不同的動作表現。除此之外還將艾麗的聊天系統加強,艾麗與喬爾在戰鬥中的對話會明顯跟戰鬥外有不同,艾麗的談話內容、發聲方式都會不同,並且隨著遊戲的進程會進一步看到差異。

除此以外,還有一點我必須要強調一下:我們不想在艾麗上作弊

作弊就是指我們在代碼上賦予艾麗一些特殊且高級的規則、甚至是超越了喬爾可執行行為範圍之外的規則(比如後文會說到一些瞬間轉移的設定)。喬爾是玩家的控制角色,是一個高度理性的角色,他在遊戲世界有一系列的限制條件,我們希望艾麗也要遵循這些規則。因為即便艾麗是一個系統控制角色,我們也希望艾麗的一系列行為都是合理的、能讓玩家信服的,而不是通過作弊來額外給艾麗提供特殊行為。總而言之就是,我們希望艾麗在遊戲世界裡是一個相當真實的角色,真實這一點將會在整個遊戲進程中有所體現。

接下來,我們從第二章開始就依次來說說上面這幾點具體的做法了。

第二章 非戰鬥跟隨AI

這一章我們來討論艾麗如何在非戰鬥的環境下跟隨喬爾,以及在跟隨喬爾的過程中會觸發什麼樣的邏輯。

1 艾麗不會使玩家卡關

首先要說的是,如果艾麗跟喬爾同時位於一個場景里,艾麗的行為看起來不能比喬爾更笨。也就是當玩家陷入一些困難的時候,玩家首先不會去選擇責怪艾麗,艾麗絕對不能成為玩家卡關的原因。當然如果劇情需要的話那就另說,比如艾麗本身的設定就是不太會游泳,玩家也就只能控制喬爾去想辦法渡過難關,我們討論艾麗的AI時不會包括這些內容。

所以,如果可能的話,艾麗一般會在玩家所視範圍內活動,並且一般只會距離喬爾幾米遠。如果玩家在一些關卡上遇見難題或者挫折時,都應該會歸因到自身而非歸因到艾麗身上。比如說在一些潛行關卡,一般來說感染者發動攻擊時都是因為喬爾(也就是玩家)暴露了位置,而艾麗一般都會緊跟在附近的掩體處、並且很難驚動感染者。

2 艾麗會觸發對話邏輯

此外,如果艾麗靠近喬爾,艾麗就會觸發一個較為複雜的對話邏輯,具體的細節我在後面章節到,但我可以提前告訴大家的是,這些對話的觸發可以取決於當時場景中的情況,比如當艾麗和喬爾靠近敵人、且喬爾處於一些危險位置時,艾麗就會說一些像「小心!」、「前面好像有感染者」之類的對話,當兩人在並肩趕路時,艾麗有時也會主動找喬爾聊天。

這個AI進一步去強化了遊戲進程中的體驗,你可以試想一下,當喬爾已經習慣於艾麗在他身邊之後,遊戲在某些關卡因為劇情的需要而把艾麗拿掉了,然後過了一段時間艾麗又重新回到喬爾身邊、並重新激活上述的種種互動時,喬爾的心路歷程就會是:

艾麗在喬爾身邊,喬爾感到放心

艾麗離開了喬爾,喬爾感到一些孤獨

艾麗還沒回來,喬爾開始感到不安

艾麗回來了,喬爾:Holy shit!Im so glad shes back!

在這個過程里,玩家會身臨其境地感受到喬爾和艾麗之間的羈絆。

3 喬爾身後的跟隨範圍

接下來再看另一個設定:跟隨範圍,這決定了同伴AI如何去讓艾麗跟隨喬爾。我們會在喬爾身邊設定一個跟隨範圍,並且讓同伴AI獲得喬爾目前所在位置的坐標。

跟隨範圍的區域細節非常多。首先它是一個範圍較廣的弧形區域,可能會在喬爾身前、也可能會會在喬爾身後,在不同環境下的區域面積會不一樣。喬爾身邊障礙物的多少也會用來調節範圍的大小,當周圍障礙物比較密集時,可跟隨區域就會小一些。

然後我們會通過計算喬爾和艾麗的移動速度來進一步確定範圍大小,有些地方我們希望喬爾帶著艾麗快速過場、有些地方我們希望他們會停下來觀察四周,不同場景都有不同的做法。

而隨著玩家的遊戲進程,跟隨範圍會不停在變化。比如在玩家接近於戰鬥時我們會把跟隨範圍收緊,周邊很安全的時候這個範圍可以相應擴大一些。

總結起來就是,根據喬爾的位置、當前所處的場景、周圍單位的多少和類型,給艾麗的AI定義一個跟隨範圍。

4 通過發射射線來確定跟隨坐標點

一旦我們確定了跟隨範圍之後,我們就進入下一步:發射射線。

我們會在範圍內以扇形的方式去掃描一些坐標點,一些我們認為看起來不會很蠢的坐標點(比如一般不會站在垃圾桶或者死掉的感染者旁邊)。然後再去按照權重去選擇一個點,這個點就是同伴AI中希望艾麗前往的坐標點。我們會根據角色站位的方向、角度,以及角色距離危險或者同伴有多遠,來分配坐標點的權重。

這個發射光線比較複雜,單單這麼說會很生硬,我下面用一個例子來說。

這裡圖中藍色的點表示喬爾的位置。在這個場景中我們希望艾麗是跟在喬爾後面的,所以經過我們先前的一個步驟已經確定好了一個弧形的跟隨範圍。那麼艾麗具體要跟在這個弧形範圍的哪裡呢,我們一步一步來看:

為了逼真,我們給這個場景再加入一個障礙好了,這塊灰色的矩形就表示一堵不能通過的牆壁,牆壁的存在會把跟隨範圍進一步減小。

然後我們以喬爾所在的坐標點為中心,向外弧發射射線,圖中這裡為了表達清晰所以只顯示了5根線,實際上我們在代碼里用到的會更多。如果這根線在過程中碰到了障礙物,那這根線就會被刪掉,我們只保留沒有碰到障礙物的線,比如圖中綠色的這些。

我們取得外弧和射線交點的坐標,然後進入下一步。

然後我們以這些坐標為中心,朝喬爾坐標的垂直方向發射射線,如圖所示:

射到障礙物上的射線我們會棄用掉。為什麼要這麼做呢?

我們想像一下我們的日常場景,當我們在跟隨一個人時、或者剛剛追上一個人時,我們大概率不會面向牆壁,就算我們靠在牆壁上等人的時候也大多面向外側。也就是我們會考慮到艾麗到達這個點之後、下一步再去跟上喬爾時的朝向,我們希望做得更自然一些,所以這些面向障礙的點我們是不會用的。經過了這一步,我們在這就剩下三個候選坐標點了。

然後我們在這三個候選坐標點的射線方向取一個距離,這個距離意味著艾麗跟上喬爾之後,短時間內可能前進的範圍。這三個距離都會對應一個坐標點,我們把喬爾的坐標跟這些坐標點連接。如果能確保喬爾等會是可以看到艾麗的,那麼這些坐標點都是可行的。

如圖所示,這三個坐標點其實都是目前為止我們可以使用的坐標點。

這個例子就暫告一段落,我們再看另外一個例子。

喬爾的位置和弧形的跟隨範圍不變,但我把障礙物變得更小了一些:

然後按照上面我們說的步驟一步步去做,得到這樣的結果:

從這個圖中我們可以看到,左邊的那個點就會存在一個問題,當艾麗往喬爾的大致方向移動後(艾麗移動時必然是朝大致的方向移動,肯定不會是直挺挺地朝喬爾移動),有可能就會跟喬爾相隔一個障礙物,這就是我們上面說到的那些很蠢的點。所以我們會在最後一步在喬爾身上發射出射線,確保艾麗在移動之後還能看到喬爾。

在遊戲的場景中我們可能會有大量障礙,大量分割空間的房間、院子、圍牆等等,通過我們上面的做法就可以保證艾麗能夠跟著喬爾進入同一個空間

我們再來看一個實際畫面的例子。

下面的圖就是喬爾和艾麗,以及旁邊那些用框框標出來的障礙物。橙色的點就是艾麗AI里候選的坐標點,如果你仔細看的話還能看到上面的權重值,這跟每個點的角度、目標值之類的東西有關,這裡就不展開了。

然後通過這張圖你會發現一個很有趣的東西:艾麗站的坐標點並不對,艾麗坐標點射出的射線是紅色的(因為射到了中間那輛車,車是障礙物)。

我當時在截這張圖的時候慢了一拍,在截圖前的一秒鐘我其實移動一下喬爾。也就是說當艾麗站在一個正確的坐標點之後,喬爾又再次移動了。你們可以注意到,艾麗腳下的那個坐標點不是橙色,而是紅色,坐標點的射線也是紅色,而非綠色,理論上艾麗應該前往那些橙色的坐標點,而她卻沒有移動。大家不要認為這是個BUG,艾麗停留在這個地方是有合理原因的。

我猜你們應該想到了,接下來要說的是:艾麗的移動時機。

5 艾麗的移動時機

你可能會在其它遊戲里見到一些非常活躍、甚至是很狂躁的同伴角色,它們不停在動,甚至還會嘗試去擠開你,根本不管你在幹什麼,你也不知道他們在幹什麼,你能見到的就是他們一直在從A點走到B點,但不知道他們為何這麼做。

為了避免這種情況,我們在艾麗AI的代碼里會記錄並監測艾麗的移動事件。

每次當艾麗想要進行下一步動作時,代碼通常就會告訴艾麗說「誒你先別動,等一等」。然後我們為艾麗設定了很多的條件,僅當這些條件成立時艾麗才會去選擇移動,並且是在接下來的一段小段時間內挑選一個時間點來移動。也就是艾麗不會在得知目標坐標之後立刻移動,而是會有一小段等待時間

當艾麗被一些什麼東西嚇到時,艾麗可能很快就會觸發移動;當艾麗距離喬爾比較遠時,艾麗也會很快就觸發移動;當喬爾走得很慢、在四處觀察時,艾麗的移動頻率也會變慢,甚至因為條件沒有觸發而暫時先靜止在原地。

6 艾麗的移動速度

在這個基礎上,我們再去確定艾麗的移動速度。

一旦艾麗選定了一個坐標點並開始移動時,AI會取得移動距離的長度,然後根據這個距離去確定艾麗應該要慢走、要跑、還是要衝刺過去

具體的計算細節這邊就不展開了,反正有了這個速度之後,我們再也不會見到當喬爾已經把艾麗拉開50米遠距離時、艾麗還在慢悠悠地走過來這種看起來很蠢的情況了。總之,這個功能就是用來計算艾麗每次要如何跟上喬爾。

關於艾麗的移動速度,我這邊還可以再說一些細節:移動速度的調整。

我們前面說了艾麗要通過走路或者跑動來移動到某個坐標,而在這個過程中的每一幀,我們都會根據喬爾的位置來實時計算、來進一步調整艾麗的移動速度,從而使艾麗看起來更自然。

比如當艾麗如果距離喬爾太遠了,我們會提高艾麗約25%的移速以便她更快追上喬爾,當然這個過程里我們也會加快艾麗的動作播放。直到艾麗已經跑完50%的距離之後,我們會讓艾麗的速度勻速下降,直到玩家看起來喬爾跟艾麗會以幾乎相同的速度在奔跑。

無論艾麗處於哪個狀態(走路、奔跑還是衝刺),我們都會有這個移動速度的調整規則,並且這個過程其實非常細微,一般來說玩家肉眼不太容易觀測到,但又能把艾麗的速度調整得非常順滑。

7 移動AI里的迴避邏輯(Dodging)

可能你們在別的遊戲里見過一些類似的迴避邏輯,就是當玩家走向一個同伴角色時,同伴角色會避開、閃到一邊去。

我們遊戲也有同樣的機制,不過後面我們慢慢發現這樣其實不算特別好。我們想像一下,在現實中你和你的朋友在一個房間里站著,然後你直挺挺地往對方的方向走到對方跟前,你的朋友有可能以為你要去揍他。

相比於直接走過去,更自然的移動方式應該是稍微帶點弧形、以對方坐標為目標來半繞著前進,最終走到對方的旁邊。

我們在觀察玩家試玩的時候的確也發現了類似的情況,因為喬爾和艾麗是接近於朋友、親人的關係,玩家通常不會採用充滿攻擊性的直挺挺走法,而是在想靠近艾麗時會稍微繞一下然後走到艾麗旁邊,然後一起看向下一個關卡目標。因此,雖然這裡我們說的是玩家控制喬爾移動時的遊戲習慣,當我們反過來要做艾麗的移動AI時,艾麗的移動方式應該也是如此

但這引出了一個問題,既然大家都會迴避,那當艾麗如果在喬爾之前到達了一個目標點,然後剛好這裡是一個窄路、把喬爾擋住了怎麼辦?

在一些樓梯上、在一些相對較窄的洞口處出現這種情況時,AI會控制艾麗開始了迴避系統里的尋路,讓艾麗在附近找到一些不會擋住喬爾的坐標點,比如窄路旁的一些小斜坡、樓梯的欄杆旁等等。然後下一步再把艾麗的朝向改變成面向喬爾,相當於示意喬爾說:「我給你讓開了,你從這邊走吧!」。這就是迴避邏輯的基礎做法之一。

此外,同伴AI還會觸發抱怨邏輯。比如無論艾麗有沒有擋住喬爾,一旦喬爾撞到了艾麗,艾麗就會做出一些反應動作,並且會觸發抱怨的對話。

8 跟隨AI這麼複雜,乾脆做個瞬間轉移好了

有人可能會說:「嘿!Max!你不是想讓艾麗緊跟在喬爾後面嗎?幹嘛不直接把艾麗傳送過去呢?瞬間轉移!」

如果你們還記得我前面所說的話,我們有一個原則就是從不作弊。我們希望遊戲中的世界是真實的,讓人有代入感的。

(這裡我插入一句,在《戰神》里阿特柔斯的同伴AI就用到了傳送,但由於《戰神》中一些更重要的遊戲設定而不得不加入傳送,否則遊戲會在一定程度上變得不太連貫,這邊就先不展開了,以後有機會再說。而《神秘海域4》則跟《最後生還者》一致,一直沒有使用傳送。)

第二個原因是關於腳步聲

如果我們用傳送的做法,艾麗的一大部分腳步聲可能都會被忽略掉,玩家在一秒前明明聽到20米外有腳步聲,然後忽然就什麼都聽不到了,這並不好。而且當艾麗用跑的方式趕上喬爾的時候,腳步的音量隨著時間慢慢變化,這本來就是我們希望達到的效果。

第三個原因則是,傳送這個行為本身就太tm驚悚了

你想想,當你遠遠地看著艾麗在遠處某個地方,然後你轉身看了一下身後,然後又回過頭看向艾麗,你發現艾麗忽然就出現在你面前。對不起我們不是一個恐怖遊戲。

我們取消傳送這件事最主要還是遊戲的原則性問題,我們不想在《最後生還者》的世界觀里加入一些匪夷所思的事情,瞬間轉移這件事情在這個世界上是說不通的。所以,我們開發組寧願花很大精力去完成這件事情,也不要去作弊。當然可能艾麗自己會認為這導致她少了一項很厲害的技能而不開心(開玩笑)。

以上這就是非戰鬥狀態下跟隨AI的基礎內容了,下一章我們來講艾麗在戰鬥狀態下的跟隨AI。


推薦閱讀:

進階篇2-AI行為樹

TAG:遊戲 | 遊戲AI | 遊戲設計 |