LV. 25
GP 4k

【討論】Unity 自製工具分享 附demo專案檔】製作RPG對話系統,用tag語言處理劇情邏輯

樓主 趴趴鼠Loading news2000tw
GP14 BP-
前言:
用regex做的,雖然它稱不是是個"語言",但我想不到更好的名詞了。
想起自己第一次做有對話系統的遊戲是3、4年前了,當時的方法蠢到用判斷行數去執行對應動作。

最近想有沒有更好的方法,更簡單,讓文本自己就能處理的方法,得出的結論就是"乾脆把文本當程式碼打"。

當然,對話系統的插件一定有很多種,也一定做得更好、更穩定。這次上來分享這個小拙作想看看各位有甚麼想法,或改善的建議。



基本概念:



demo 專案影片 (用之前參加game jam的美術圖):

說明:
整個專案除了玩家、攝影機移動之外都是用這個工具進行的,(例如對話、切換場景、劇情邏輯判斷)。

一開始選擇語言,第一個場景示範切換場景。
第二個主要遊戲場景中主要的劇情邏輯有:
還沒跟兒子對話前,跟村民的對話劇情是日常的閒聊話。
第一次跟兒子對話,他會要求媽媽拿玩具給他,這時候跟小朋友的對話內容改成要求玩具,拿完玩具再跟小朋友對話則變成閒聊話2。
玩具給兒子後,他要求媽媽找5顆糖果給他,在糖果沒收集齊全前,跟兒子的對話都會說"不夠,目前只有xx顆糖果"。其中xx是動態變數。村民的對話也變成要求糖果,拿完糖果後對話變成閒聊2。

每個可對話物件都是在自己1個文本裡判斷的。
範例 兒子的文本:

其他文本檔案在

專案下載與語法說明 連結

以下簡略說明一下語法,小屋有比較詳細的使用說明:

  • 用<story> </story> 開頭、收尾。
  • 非tag以外內容需要出現<>, 則加上 \ (跳脫符號) 在<>前。  (我regex能力的最限就是想出這個方法了 )
    • 例如<l > \<color=red\> Red content text! \</color\> </l>

<l> </l>
"l" 代表每一個對話。

<if> </if>
達成條件才會進行裡面的內容。

<Select> </Select>
創建選單,只能搭配<opt></opt>的tag。

主要的tag就這些,接下來是參數。


animation(gameobjectName,clipName)
尋找場上的物件名稱為"gameobjectName"的物件,並播放動畫名稱為"clipName"的動畫。

audio(gameobjectName, [stop|play|pause])
尋找場上的物件名稱為"gameobjectName"的物件,並設定該AudioSource的狀態。

title ="name"
對話框的標題。

by="gameobjectName"
如果對話框是浮在物件上的風格,用by="物件名稱"找尋該物件。

img([left|middle|right] , path)
如果對話框是像galgame那樣固定畫面的,我預設有分左、中、右,3個image欄位。圖片要放在Resources資料夾下。 left/ middle/ right是在prefab裡面指定的。

set("variableName" = value)
設定變數。若是"temp_"開頭的,會放在暫存的字典裡,對話結束就清除,方便用來做一些無關緊要的選擇性對話。 反之變數會存在整個遊戲(static),但遊戲關掉就沒了,所以請記得處理RPGCore.cs 裡面的StoryRecord存讀取。可以用我這個存讀檔的腳本(字典不能存json,只能存bin)。

$[key]
讀取自訂變數。 例如 $[temp_a]。

enable / disable( obj1,obj2,obj3.....)
開啟或關閉物件。 用find找並加入紀錄中,所以一開始的物件應都設開啟狀態,透過一個開始的文本把物件關閉並記錄,之後才能再開啟。
例如demo有個文本單純就是玩家經過觸發隱藏物件,但因為沒有內容所以馬上結束。
<story disable(toy2)></story>

其他
  • 想擴充自己的標記的話,請照著這個格式:functionName( arg1, arg2 ,arg3,arg4.......)在StoryReader.cs裡面的ReadArgs()方法裡有個標註 YOUR OWN SCRIPT FUNCTION 的地方處理。
  • 一行內arg可用不只一個。


單純工具主要有RPGCore.cs , StoryReader.cs 和 OptionButton.cs。

  • RPGCore主要放Regex和方法,不用實作。要新增語言請找到public enum Lang。然後在Resources資料夾下新增個對應名稱的資料夾。
  • StoryReader 主要處理arg和tag解讀與和UI的互動,放在對話框prefab。用StartConversation()開始對話。
  • OptionButton 放在選項按鈕prefab,單純回傳告知StoryReader 選擇了什麼。
  • 多個StoryTrigger.cs是用來觸發對話的。


目前就這樣,還有些小bug和擴充的內容待加強。
(若執行對話時盪掉,請檢查是否每個tag都有對應的close tag)


至於拆解巢狀regex的血汗研究可以看 這篇這篇
簡單說來,regex拆出來的結果長這樣:

tag會按照順序列出,然後用迴圈找出對應的close tag:




感謝收看
14
-
未登入的勇者,要加入 2 樓的討論嗎?
板務人員:

240 筆精華,12/29 更新
一個月內新增 2
歡迎加入共同維護。


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】