電子遊戲中的 NPC · 四個可遊玩世界

電子遊戲中的 NPC:非玩家角色如何運作(附可遊玩示範)

製作你自己的 NPC 電子遊戲

什麼是電子遊戲中的 NPC?看看 NPC 如何被打造、如何行動,並遊玩四款真實的瀏覽器 3D 遊戲,裡頭的非玩家角色會移動、交談與反應。

✦遊戲
製作一個 NPC 電子遊戲

電子遊戲中的 NPC 就是非玩家角色:一種不直接受玩家控制,卻佔據空間、保有狀態,並對世界中的條件做出反應的實體。這個詞刻意定義得很寬,而正是這樣的寬度造成了大部分的混淆。一個有作息表的店主、一個跟著你穿過走廊的隊友,以及一個只重複一句話的遊走商人,全都是 NPC,但它們的打造方式不同,執行時的成本也不一樣。

本頁說明 NPC 究竟是什麼、一個 NPC 如何被打造出來,以及如何把它和一個只是看起來活著的腳本觸發器區分開來。本站四個可遊玩世界會作為實例 — Agent Sprite Forge、The Cyclops' Island、Mini World,以及 3D 遊戲建造器本身 — 讓你能走到 NPC 面前觀察它的行為,而不只是閱讀相關說明。

快速解答:在電子遊戲中,什麼算是 NPC

NPC 是遊戲世界中任何不直接受玩家控制的角色。它擁有位置、狀態,以及至少一種不需玩家按下按鈕就會觸發的行為。如果你把玩家從場景中移除,而這個角色仍會做某件事 — 走一條路線、開一扇門、對附近的事件做出反應 — 它就是 NPC。

角色與機制之間的分界線在於狀態的歸屬。角色擁有能跨影格持續存在的變數:目前生命值、目前目標、目前巡邏索引、目前對話節點。機制在實務上則是無狀態的 — 它在條件滿足時觸發一次,然後就結束了。一塊打開閘門的壓力板是機制。一個對閘門開啟做出反應、記得你剛才站在那裡,並改變自己路線的守衛則是 NPC。差別不在於視覺精緻度,而在於是否有任何東西能在事件發生的那一個影格之後存留下來。

電子遊戲 NPC 簡史

1970 年代末與 1980 年代的文字冒險遊戲,把 NPC 當作剖析器辨識的目標來處理。一個角色僅以剖析器所辨識的具名名詞,加上一小段旗標的形式存在。早期文字冒險遊戲中的小偷,只要你和他在同一個房間、且他還沒偷過,就會偷走一件物品 — 那是一個只有兩個變數的 NPC:在場,以及一個已偷竊旗標。沒有尋路、沒有動畫、沒有排程。行為存在於旗標裡,而不是角色裡。

精靈時期的 NPC 加入了動畫與碰撞,但行為仍維持單薄。一個鎮民會沿著固定的兩點迴圈行走,當玩家進入某個半徑內時播放待機動畫,並在接觸時開啟對話框。重要的技術變化是,NPC 如今在物理世界中擁有位置,因此它必須很省。在 8 位元與 16 位元硬體上,螢幕上同時出現數十個 NPC 時,每個 NPC 只分到幾個位元組的狀態,並執行一個複雜度不超過距離比較的每影格檢查。

排程驅動的 NPC 出現於記憶體與 CPU 預算足以讓一個角色獨立於玩家所在位置而存在之時。一個擁有營業時間數值、一個住家路徑點與一條行走路線的店主,在你抵達時可能正在別處,而這種不在場對玩家而言是可解讀的。其實作方式是一個時鐘加上一張查找表:遊戲時間 21 點時,以住家路徑點為目標;08 點時,以商店為目標。玩家從不會看見那張表,只會看見其結果。

生成式 NPC 是當前這個時代。與其為每個狀態撰寫一句台詞,你改為撰寫一段角色描述,然後讓模型在執行時期產生對話、短句或行為。取捨不再只是儲存空間,而是確定性:生成出來的台詞無法被完整預覽,因此你需要針對語氣、長度,以及 NPC 被允許提及的內容設下護欄。在 3D 遊戲建造器中,NPC 的提示詞被限制為一段描述加上一小組行為,正是基於這個理由。

現代 NPC 如何被打造

每個 NPC 都是一疊彼此協同的五個部分:狀態、導航、動畫、對話與感知。狀態是 NPC 所擁有的資料 — 生命值、目標、巡邏索引、對話節點、警戒等級。導航是它在各點之間移動的方式。動畫是移動與待機時刻被呈現的方式。對話是為了回應各種條件而產生的文字與語音。感知則是告訴 NPC 有某件事改變了的輸入,通常是距離檢查、視線射線投射,或觸發體積的重疊。

在典型的專案中,這些部分各自存在於不同的地方。狀態是 NPC 實體上的一個腳本或元件 — 用 Unity 的說法是一個 MonoBehaviour,在 Godot 中是一個 Node 腳本,在瀏覽器 Three.js 專案中則是一個附加到網格的純物件。導航要嘛是路徑點資料,要嘛是導航網格。動畫是一個帶有具名片段的狀態機,例如待機、行走、攻擊。對話是一個資料檔,通常是一張小型節點圖或以狀態為鍵的表格。感知通常是一個碰撞形狀加上一項每影格檢查。

最常見的失敗模式,是狀態與動畫彼此脫節。NPC 處於追逐狀態,卻仍在播放待機片段,於是它就朝著你滑行,雙腿卻沒有擺動。修正方法不是加入更多動畫,而是讓程式碼中只有一個地方寫入目前狀態,並且只有一個地方讀取它來選擇片段。當這兩者存在於不同的腳本中,你就會看到滑行;當它們是同一個函式,就不會。

第二常見的失敗,是導航與關卡不符。一條對照舊配置撰寫的巡邏路線,會在幾何改變後把 NPC 送進牆裡或送下懸崖。在瀏覽器專案中,最省又最穩健的做法,是把巡邏點保留為具名的空物件,並在載入時重新解析它們,這樣移動一道牆就不會讓路線失去依附。

感知正是 NPC 變得昂貴的地方。每個 NPC 每影格各做一次射線投射,對少數幾個角色還行,但對數百個就顯得浪費。常見的最佳化做法,是共用的空間網格、檢查間隔,以及在任何射線投射執行前先做一次早期的距離排除。如果一個 NPC 距離 40 公尺遠,而它的感知半徑是 8,那麼那次射線投射根本就不該發生。

每個部分在場景中的所在位置

狀態:放在 NPC 實體本身。保持精簡 — 幾個數字,加上一個字串用於目前對話節點。如果你需要更多,就把這個 NPC 拆成兩個角色。

導航:以一份世界座標點清單的形式,與場景一起儲存,而不是烘焙進模型裡。動畫:以骨架上的具名片段形式存在,由單一的狀態切換來選擇。對話:放在獨立的資料檔中,讓撰寫者能在不碰程式碼的情況下編輯它。感知:以一個觸發體積加上一項距離檢查的形式存在,並把射線投射放在最後一步,而不是第一步。

1

01

把 NPC 模型放進場景,並附加一個帶有目前狀態、目標與巡邏索引欄位的狀態元件。

2

02

加入三或四個路徑點物件並為它們命名,讓路線在關卡被編輯後仍能保留。

3

03

接上一個至少包含待機與行走的動畫狀態機,並只從目前狀態值來驅動它。

4

04

加入一個感知觸發體積,其大小對應 NPC 的察覺半徑。

5

05

把對話寫成一張以狀態為鍵的小型表格,並為沒有對應的狀態準備一句預設台詞。

6

06

在載入時重新解析路徑點與對話鍵,然後移動一道牆來測試,確認巡邏仍能運作。

四個可遊玩世界,四種 NPC

理解 NPC 行為最清楚的方式,就是站到其中一個旁邊,並改變它能看見什麼。Neta Studio 上的這四個世界各自展示了一種不同的行為模式。把它們打開,走進 NPC 的感知範圍,然後再走出來,看看有什麼改變。

Agent Sprite Forge 所執行的 NPC,是由一段簡短的角色描述加上一小組狀態來定義的。走到其中一個面前,它的回應便會從那段描述生成,並被限制在這個世界所暴露的狀態之內。有趣的測試是重複:接近同一個 NPC 兩次,比較第二次的回應變化有多大。那份變異來自模型,而非世界 — 狀態機是固定的。

The Cyclops' Island 使用一個大型 NPC,並採用追逐與搜索的模式。當玩家位於感知半徑之內,獨眼巨人便會追擊;當玩家切斷視線,它會搜索最後已知的位置,然後返回巡邏路線。正是搜索這一步,讓它讀起來像個角色,而不是一枚追熱飛彈 — 它會依據過時的資訊行動。

Mini World 在幾個短迴圈上放置了數個小型 NPC,並附有互動提示。它們的行為刻意保持單薄:行走、暫停,當玩家在一公尺以內時做出回應。這裡的價值在於數量。你可以同時觀察五、六個,並看見一個令人信服的 NPC 迴圈實際上有多省。

3D 遊戲建造器則是你直接放置與設定 NPC 的地方。每個 NPC 都會獲得一段描述、一條巡邏路線與一組狀態。打造一個小東西 — 一個房間、一個 NPC、一條路線 — 然後測試它的邊界:把感知半徑縮小到 NPC 永遠不會注意到你,再把它放大到 NPC 永遠不會停止注意到你。這兩個極端之間那段有用區帶的寬度,就是調校的難題,而它在每一款引擎裡都存在。

關於效能的一點說明。在瀏覽器專案中,NPC 的成本主要來自感知檢查與動畫,而不是幾何。十個每影格做射線投射的 NPC,會比十個共用間隔檢查的 NPC 更耗成本,即使高細節模型是掛在那些採用間隔檢查的 NPC 上。如果場景在 NPC 活動時出現卡頓,先檢查感知迴圈。

  • Agent Sprite Forge以描述驅動的 NPC,搭配受限制的生成式回應。用它來看看一小組狀態加上一段角色提示詞,如何產生不離題的對話。
  • The Cyclops' Island單一大型 NPC,具備追擊、搜索與返回巡邏等狀態。用它來研究依據過時資訊行動如何讀起來像智慧。
  • Mini World數個輕量 NPC 在短迴圈上活動,並附有接近提示。用它來看看一個角色在讀起來有存在感之前,需要的行為可以少到什麼程度。
  • 3D 遊戲建造器放置 NPC、設定描述、繪製巡邏路線,並調校感知半徑。用它來找出介於永遠不會注意到你的 NPC 與永遠不會停止的 NPC 之間的那段可用區帶。
Little Ritual — 一顆小行星上的任務 NPC。

為什麼賣出一個 NPC 的是行為,而不是畫面

一個低細節的角色,會走一條路線、在門前暫停,並在你回來時出現在別處,讀起來就是活的。一個高細節的角色,站定在原地、重複著一句台詞,讀起來就像家具。玩家不是在評價多邊形。玩家是在建立一個關於這個角色想要什麼的模型,而那個模型來自時機與位置,不是來自網格。

其機制是期待。如果一個角色早上在市場、晚上在家,玩家就會形成一個假設 — 這個角色有作息 — 而這個假設會在第二次造訪時被確認。那份確認就是整個效果。它只需要一個時鐘與一張查找表。這件事無法透過替一尊雕像增加細節來取代,因為雕像從不會否定或確認任何事。

這就是為什麼來自古老許多的遊戲、由排程驅動的 NPC 至今仍被討論,而視覺上更出色的靜態 NPC 卻被遺忘。行為才是內容。模型只是包裝。如果你正在瀏覽器編輯器中打造專案,而時間有限,請先把它花在狀態轉換與巡邏路線上,再考慮花在貼圖上。

如何分辨 NPC 與腳本觸發器

NPC 與觸發器都會對玩家做出反應,這就是它們在設計評審中常被混淆的原因。其中的區別在於事件之後是否有任何東西存留下來。當你要判斷眼前是哪一種時,可以把下方的訊號當作檢查清單。

這張表不是純度測試。許多遊戲會用觸發器來啟動 NPC 的行為 — 一個把守衛從巡邏切換為警戒的觸發體積。這很正常,也正確。問題在於當觸發器被當成一個角色呈現給玩家時:它觸發一次,這個角色之後再也不對任何事做出回應,於是那份錯覺在第二次遭遇時就崩解了。

訊號它是 NPC它是腳本觸發器
重複出現同一個角色在第二次遭遇時仍會回應觸發一次後就不再觸發
狀態擁有能在影格之後存留的變數 — 警戒等級、巡邏索引除了已觸發/未觸發的旗標之外,沒有任何狀態
位置在兩次遭遇之間會在世界中移動停留在被放置的地方
反應範圍依情境(白天、生命值、距離)做出不同的反應無論情境如何都是相同的回應
失敗可能會卡住、失去目標,或尋路不佳不會失敗 — 它要嘛觸發了,要嘛沒有
成本每影格的感知與動畫預算事件過後可忽略不計
對話從以狀態為鍵的集合中選出一句台詞播放一句固定的台詞
The Cyclops' Island — 一個帶有碰撞的敵方 NPC。
Ashenmere — 一個你在決鬥時能讀懂的對手 AI。
Mini World — 走進一個世界,認識其中被放置的角色。

走進它所屬的那個世界

精靈是一個無處可站的角色。最後這一步是別人都不提供的:把你剛建立好的圖集,放進一個有人能四處走動的世界 — 一座小島、一顆行星、一個下雨的街角。這個網站上的每一個世界,都是從一段書面描述打造而成,並發布成一個你可以遊玩的頁面。

回到 3D 遊戲建造器

全部 31 個完成的 3D 世界、遊戲與場景都放在同一頁 — 每一個都能玩。

平台: Neta Studio頁面: 電子遊戲中的 NPC:非玩家角色如何運作(附可遊玩示範)接著閱讀: /explore/guide/what-is-a-non-player-character · /explore/guide/what-are-npcs · /explore/guide/npc-behavior
×