准備兩個C#代碼+1個txt文本
多數報錯都是代碼的公開變量沒有獲取到,導致空引用!
1:對話框內容文本文件.txt
自行准備文本信息(如果顯示的是亂碼,請更改編碼格式為UTF-8)
A 你好啊,勇士! B 你好,老爺爺. A 歡迎來到帕利鎮,我是這的村長,薩羅特. B 喔,原來是村長啊,您好!
2:NPC代碼,掛在到要對話的物體對象身上
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class Sensei : MonoBehaviour 6 { 7 public GameObject talkUI;//對話框面板 8 public bool talkUIState;//對話框狀態 9 public GameObject buttonR;//顯示在NPC頭上的按鍵圖片 10 11 void Update() 12 { 13 if (buttonR.activeSelf && Input.GetKeyDown(KeyCode.R)) { 14 talkUIState = !talkUIState; 15 talkUI.SetActive(talkUIState); 16 } 17 } 18 19 private void OnTriggerEnter2D(Collider2D c) { 20 if (c.gameObject.CompareTag("Player")) { 21 print("觸碰了村長的觸發器"); 22 buttonR.SetActive(true); 23 } 24 } 25 26 private void OnTriggerExit2D(Collider2D c) { 27 if (c.gameObject.CompareTag("Player")) { 28 print("離開村長觸發器"); 29 buttonR.SetActive(false); 30 } 31 } 32 }
3:對話系統(核心)
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using UnityEngine.UI; 5 public class TalkSystem : MonoBehaviour { 6 [Header("UI組件")] 7 public Text textLabel;//要更改的文字 8 public Image talkImage;//說話的頭像 9 public GameObject talkPanel;//對話面板 10 11 [Header("對話文本文件")] 12 public TextAsset textFile;//對話文本文件 13 public int index; 14 List<string> textList = new List<string>();//存儲文字的集合 15 public float textSpeed;//文本顯示速度 16 public bool textIsOver;//文本是否顯示完畢 17 18 [Header("頭像")] 19 public Sprite face1, face2;//頭像1,2 20 21 private void Awake() { 22 //讀取文件 23 GetTextFormFile(textFile); 24 } 25 26 void Update() { 27 PrintTlakText(); 28 } 29 30 /// <summary> 31 /// 當物體會被激活顯示時觸發,生命周期速度比start塊 32 /// </summary> 33 private void OnEnable() { 34 //就顯示文字 35 //textLabel.text = textList[index]; 36 //index++; 37 textIsOver = true; 38 //開啟協程 39 StartCoroutine(SetTextUI()); 40 } 41 /// <summary> 42 /// 從文件讀取文本 43 /// </summary> 44 /// <param name="f"></param> 45 void GetTextFormFile(TextAsset f) { 46 textList.Clear(); 47 index = 0; 48 49 //將文本按行切割,變成數組 50 var lineDate = f.text.Split('\n'); 51 52 //循環將數組中的字符添加到 集合中 53 foreach (var l in lineDate) { 54 textList.Add(l); 55 } 56 } 57 58 /// <summary> 59 /// 輸出對話文本 60 /// </summary> 61 void PrintTlakText() { 62 //判斷達到了最后一句話 63 if (Input.GetKeyDown(KeyCode.T) && index == textList.Count) { 64 //隱藏對話框 65 talkPanel.SetActive(false); 66 //下標歸0 67 index = 0; 68 return; 69 } 70 //如果按下按鍵 並且 這行顯示完成了,才能開始執行協程 71 if (Input.GetKeyDown(KeyCode.T) && textIsOver) { 72 //開啟協程 73 StartCoroutine(SetTextUI()); 74 } 75 } 76 77 /// <summary> 78 /// 創建協程 79 /// </summary> 80 /// <returns></returns> 81 IEnumerator SetTextUI() { 82 //一開始設置為false 83 textIsOver = false; 84 //清空顯示的文本 85 textLabel.text = ""; 86 87 //判斷當前行文字為A or B時,改變對應的頭像 88 //Trim()刪除字符串頭部及尾部出現的空格, 89 switch (textList[index].Trim()) { 90 case "A": 91 print("當前是A"); 92 talkImage.sprite = face1;//切換頭像 93 index++;//跳過顯示 94 break; 95 case "B": 96 print("當前是B"); 97 talkImage.sprite = face2; 98 index++; 99 break; 100 } 101 102 //循環獲取當前下標的文本長度 103 for (int i = 0; i < textList[index].Length; i++) { 104 //累加當前行的所以有符串 105 textLabel.text += textList[index][i]; 106 //等待時間(變量)並返回 107 yield return new WaitForSeconds(textSpeed); 108 } 109 //執行完成后將文本輸入完畢設置為true 110 textIsOver = true; 111 //下標自增 112 index++; 113 } 114 115 }
效果GIF(請忽視移動動畫...)
原教程地址:Unity教程:<對話系統>#01:簡介&UI制作_嗶哩嗶哩_bilibili