對話系統 其實就是由一連串的字串組成的
只是要怎麼讀取那些要自己慢慢寫
最基礎的對話系統就是兩三個string然後用一個label去讀取 ,像這樣
每次點擊都會讀取一個string 到達到最大長度-1為止
1 | using UnityEngine; |
而接下來就是延伸這個基礎的對話系統了
我想要的功能有
1.按鍵跳下一格
2.顯示對話人物
3.不必選擇Yes or No
4.遇到npc 按下某一個按鍵可開始對話
做完看似如下
一、保存對話資料
一般很多都是載入xml或txt資料來讀取對話,但我比較喜歡這種
其實也可以直接看上下就做出一個比較好的對話系統,但我看不懂IEnumerator那個使用方式…
如果有人願意解釋一下當然是最好的啦XD 但身邊沒什麼程式人… QQ
所以我使用了他的保存對話資料的方式 , 大概看一看就懂了
他使用了兩層
ConversationData - SpeakerData 然後就開始填對話者、講的話
我的話是填了三層
Dialog_Npc_Data - Dialog_Chapter - Dialog_eachPart_sentence
我的想法是,每個NPC都有一個對話資料(Dialog_Npc_Data),而NPC你很常看到他會有講話的分支,就像故事的章節一樣(Dialog_Chapter),而每個章節保存了很多詳細的對話內容(Dialog_eachPart_sentence)
像是 小紅帽故事書(對話資料),分三個章節(Dialog_Chapter),第一個章節小紅帽出去玩,然後
奶奶: 走阿 永遠不要回來了
小紅帽 : 是的船長
像這樣,每個章節內都保存了哪個人物講什麼
因此 Dialog_eachPart_sentence 這個Class內容就是
Dialog_eachPart_sentence
1 | using UnityEngine; |
speakr就是誰講的,sentence就是這個人講了幾句話,pos是定義這個人的頭像位置在哪
Dialog_Chapter
是章節,定義了有幾個”人”去講話
1 | using UnityEngine; |
最後是對話資料,定義了有幾個章節、這個對話資料的ID,indexpart可以不用理,當初是想用它來定義當前講到第幾章節
1 | using UnityEngine; |
看完遊戲蠻牛那個教學後,改一改 創建一個對話資料,對話資料的內容就會像這樣
PS. 省略了創建對話資料那邊的過程,蠻牛上有
接下來就是創建一個對話系統來使用這些對話資料了
part 1 宣告一個字典保存所有對話資料,以後用Key來尋找這個資料、一個List來把對話資料載入
1 | public Dictionary<int, Dialog_Npc_Data> System_npc = new Dictionary<int, Dialog_Npc_Data>(); |
在Awake方法中把資料加入字典裡
1 | void Awake() |
part 2 宣告一些需要用到的資料
Npc_ID是NPC的ID,index_Chapter是哪個章節,isDialog是判斷有沒有在對話
1 | public bool isDialog = false; |
接下來定義兩個函數,一個是外部調用這個對話系統時傳入值的函數,一個是初始化的函數
傳入值有兩個,一個是要讀取的NPC的ID,也就是哪個對話資料,一個是Chapter,要讀取的章節
想像一下,當你接觸到某個npc範圍的時候,按下空白建,然後開始對話,然後就把某個npc的id還有定義好的章節傳入
1 | public void SetDialogInfo(int Npc,int Chapter) |
當isDialog = true的時候 就開始對話了,開始對話每當按下滑鼠左鍵,最底層的index_sentence就開始跑,這跟最上面那個基礎對話機的原理一樣
其中有呼叫一個函數StartDialog(),這個函數用來顯示、讀取對話的內容
1 | void Update() |
接下來再宣告一些會用到的東西
1 | //part4 |
Visible_Message用來在螢幕上顯示 對話的內容
Visible_Spaker是對話的人
current_content是用來回傳的
Left、right是用來定義這個對話人物的位置在哪,傳統都是看到人物一個在左邊,一個在右邊
然後就是實現上面的StartDialog方法了
1 | //傳入哪一段之後,就開始把這一段給看完 |
第一行是每個npc資料裡面都會有個speaker,,把顯示的UISprite換成當前npc的章節裡面的speaker的名子(好拗口
第2.3.4行是定義了位置訊息
第5行是 UIlabel顯示的內容,透過ChapterSentence()方法得到
ChapterSentence()方法內容是
1 | string ChapterSentence() |
跟基礎對話系統差不多,獲得兩個最大可讀取的內容長度然後更新這兩個來讀取整個章節
應該都不算太難,看看應該就懂了
難的還是遊戲蠻牛那個方法來讀取,感覺好多了“
完整版
1 | using UnityEngine; |
然後使用另外一個class來調用,我是放在npc上面
1 | using UnityEngine; |