Unity 實現一個簡易可拓展性的對話系統

? ? ? ? 本人能力有限,一切實現僅供參考,如有不足還請斧正

????????起因是我看到學校社團內有人做了對話系統的分享,我想了想之前沒寫過這種東西,而Fungus插件教程太老了,NodeCanvas插件學習成本又比較高,我就干脆尋找資料 加上自己迭代一下,花了一天時間完成了這個對話系統

目錄

1.介紹

2.核心腳本

對話管理器

對話事件

對話配置腳本

對話節點腳本?

3.使用指北

路徑配置

關于特性

關于接口?

關于UI?

其余內容請自行查看源碼


? ? ?Github:??Haki-sheep/Haki-sheep-UnityTools at DialogTools-dev1.0?

? ? ? ? 演示視頻:

Unity一個簡易可拓展的對話系統

1.介紹

? ? ? ? ?這個對話系統并不是可視化編輯節點(像是NodeCanvas插件那種),但也支持一鍵將Excel表轉為So文件,通過配表的方式輕量化這一過程

? ? ? ? 首先,算上DEMO一共632行,去掉以后可能?不到四百行 所以十分輕巧

? ? ? ? 但是由于代碼量擺在那,所以目前本對話系統只支持小玩具, 今后我說不定會將其拓展為課編輯節點的系統,當然,目前我個人使用起來還是比較方便的,畢竟是自己編寫的系統

? ? ? ? 其次 Base只涉及到了Odin插件EPPLUS 以及一個單例基類 無需其他支持

2.核心腳本

對話管理器

? ? ? ? 對話流程如下:

using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;public class DialogManager : SingltonMono<DialogManager>
{#region 基礎配置//配置相關private DialogConfig curDialogConfig;private int nodeIndex;public bool nodeNotOver => nodeIndex < curDialogConfig.nodeList.Count - 1;//角色相關private string characterName;private Sprite characterAvatar;//外部 可做替換public Player player;public DialogMainUI dialogMainUI;public SelectUI selectUI;#endregion#region 對話流程 /// <summary>/// 開始對話/// </summary>/// <param name="dialogConfig">想要對話角色的配置</param>/// <param name="nodeIndex">從第幾個節點開始對話</param>public void StartDialog(DialogConfig dialogConfig, int nodeIndex = 0){if (curDialogConfig == dialogConfig) return;//不要重復對話curDialogConfig = dialogConfig;this.nodeIndex = nodeIndex;characterName = curDialogConfig.characterName;characterAvatar = curDialogConfig.characterAvatar;StartCoroutine(PlayNode(curDialogConfig.nodeList[nodeIndex]));}public void CeckCharacterInfo(DialogNode node, Image ui_characterAvator, Text ui_characterName){//角色的信息if (node.player){ui_characterName.text = player.name;ui_characterAvator.sprite = player.Avator;}else{ui_characterName.text = characterName;ui_characterAvator.sprite = characterAvatar;}}private IEnumerator PlayNode(DialogNode node){dialogMainUI.Show();CeckCharacterInfo(node, dialogMainUI.ui_characterAvator, dialogMainUI.ui_characterName);//開始事件OnEvent(node.onStartEventList);yield return OnBlockEvent(node.onStartEventList);//打字機yield return Typing(node.content, dialogMainUI.ui_contentText);//等待交互while (!Input.GetMouseButtonDown(0)) { yield return null; }//結束事件OnEvent(node.onEndEventList);yield return OnBlockEvent(node.onEndEventList);if (nodeNotOver){nodeIndex++;StartCoroutine(PlayNode(curDialogConfig.nodeList[nodeIndex]));}else{CloseDialog();}}private void OnEvent(List<IDialogEvent> dialogEvents){foreach (IDialogEvent sEvent in dialogEvents){sEvent.Execute();}}private IEnumerator OnBlockEvent(List<IDialogEvent> dialogEvents){foreach (IDialogEvent sBEvnt in dialogEvents){IEnumerator enumerator = sBEvnt.ExecuteBlock();if (enumerator == null) continue;yield return enumerator;}}public void CloseDialog(){StopAllCoroutines();curDialogConfig = null;nodeIndex = 0;dialogMainUI.Hide();}#endregion#region 打字機相關 public float delayBetweenContent = 0.1f;private Dictionary<string, string> keywordDic = new Dictionary<string, string>();public void SetKeyword(string key, string value){keywordDic[key] = value;}public void RemoveKeyword(string key){keywordDic.Remove(key);}private IEnumerator Typing(string content, Text ui_contentText){StringBuilder builder = new StringBuilder();foreach (var item in keywordDic){content = content.Replace(item.Key, item.Value);}foreach (var s in content){builder.Append(s);ui_contentText.text = builder.ToString();yield return new WaitForSeconds(delayBetweenContent);}}#endregion#region 資源管理public T GetDialogConfig<T>(string path) where T : ScriptableObject, new(){return Resources.Load<T>(path);}#endregion}

對話事件

這里我就展示其中一種事件,檢查某一樣子東西玩家是否已經應有 從而跳過對話

using System.Collections;
[DialogEvent("CheckKeyWordEvent")]
public class CheckKeyWordEvent : IDialogEvent
{public void ConverString(string excelString){}public void Execute(){//檢查是否有選中物品 TODO:條件可以替換if (Player.Instance.selectItem != null){DialogManager.Instance.CloseDialog();}}public IEnumerator ExecuteBlock(){return null;}
}

對話配置腳本

using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Tools", fileName = "創建新角色")]
public class DialogConfig : SerializedScriptableObject
{//角色名稱public string characterName;//角色頭像public Sprite characterAvatar;//顯示索引,開啟翻頁[ListDrawerSettings(ShowIndexLabels = true, ShowPaging = true)]public List<DialogNode> nodeList = new List<DialogNode>();
}

對話節點腳本?

using System.Collections.Generic;
/// <summary>
/// 對話節點配置
/// </summary>
public class DialogNode
{//是否是玩家public bool player;//說的內容public string content;//對話事件public List<IDialogEvent> onStartEventList = new List<IDialogEvent>();public List<IDialogEvent> onEndEventList = new List<IDialogEvent>();}

3.使用指北

路徑配置

????????這個文件填寫你的Excel表和so文件想在的位置

????????但是我推薦將so文件放在Res下面 方便管理器讀取

? ? ? ? ?如果有報錯就把你的DialogImprotSetting的路徑放在這里面

關于特性

? ? ? ? 這個特性內填寫你的事件名稱即可 可以不和腳本一樣 只需要和Excel表之中一樣便可以讀取

關于接口?

? ? ? ? 事件需要繼承這個接口

阻塞執行?里面直接return nul即可 因為外部會判斷

當然你直接yield rerun null也可以,但是會造成延遲一幀后才執行其他語句

? ? ? ? UI接口的話可以選擇性繼承,因為里面也沒什么方法,可以自己寫

關于UI?

? ? ? ? 在DialogManager里有兩個UI的對象,其實所有在外部這個注釋下的字段都可以自行做替換

? ? 只要讓Manager得到了你UI身上下面這些信息即可(方式自行選擇比如事件中心或者訂閱回調的方式)

? ? ? ? 剩下的UI樣式之類的自行配置即可

其余內容請自行查看源碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73212.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73212.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73212.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux常用指令(6)

今天我們繼續學習一些linux常用指令,豐富我們linux基礎知識,那么話不多說,來看. 1.cp指令 功能描述&#xff1a;拷貝文件到指定目錄 基本語法&#xff1a;cp [選項] source dest 常用選項&#xff1a;-r&#xff1a;遞歸復制整個文件夾 拷貝文件&#xff1a; 拷貝文件夾&am…

Vue 3 中的路由傳參詳解※※※※

前言 在Vue應用中&#xff0c;路由傳參是非常常見的需求&#xff0c;它允許我們在不同的組件之間傳遞數據。Vue Router提供了兩種主要的方式來傳遞參數&#xff1a;query參數和params參數。下面我們將詳細探討這兩種傳參方式的使用方法和注意事項。 一、query參數 Query參數…

如何創建一個socket服務器?

1. 導入必要的庫 首先&#xff0c;需要導入Python的socket庫&#xff0c;它提供了創建和管理socket連接的功能。 python import socket 2. 創建服務器端socket 使用socket.socket()函數創建一個服務器端的socket對象&#xff0c;指定協議族&#xff08;如socket.AF_INET表示…

lua垃圾回收

lua垃圾回收 lua 垃圾回收 lua 垃圾回收 collectgarbage(“count”)獲取當前lua腳本占用內存字節數(單位為KB)。 collectgarbage(“collect”)執行一次垃圾回收。 xxxnil 將變量置為空&#xff0c;會釋放內存。 lua中的機制和c#中回收機制很類似 解除羈絆(置為空)。 --垃圾回…

友思特應用 | 行業首創:基于深度學習視覺平臺的AI驅動輪胎檢測自動化

導讀 全球領先的輪胎制造商 NEXEN TIRE 在其輪胎生產檢測過程中使用了基于友思特伙伴Neurocle開發的AI深度學習視覺平臺&#xff0c;實現缺陷檢測率高達99.96%&#xff0c;是該行業首個使用AI平臺技術推動缺陷檢測自動化流程的企業。 將AI應用從輪胎開發擴展到制造過程 2024年…

前后端+數據庫的項目實戰:hbu迎新網-較復雜(下)javaweb

目錄 十一、實現對內容的富文本編輯&#xff08;換行、圖片顏色等等樣式&#xff09; &#xff08;1&#xff09;下載富文本編輯器&#xff0c;引入資源 &#xff08;2&#xff09;將原項目的內容部分替換為富文本編輯器 1、替換添加頁面 2、替換修改頁面&#xff08;和添…

腳本語言 Lua

概念 Lua由標準C編寫而成&#xff0c;幾乎在所有操作系統和平臺上都可以編譯、運行。Lua腳本可以很容易地被C/C 代碼調用&#xff0c;也可以反過來調用C/C的函數&#xff0c;這使得Lua在應用程序中可以被廣泛應用。Lua并沒有提供強大的庫&#xff0c;它是不適合作為開發獨立應…

【數據分享】2000—2024年我國鄉鎮的逐月歸一化植被指數(NDVI)數據(Shp/Excel格式)

之前我們分享過2000—2024年我國省市縣三級逐月歸一化植被指數&#xff08;NDVI&#xff09;數據&#xff0c;該數據是基于NASA定期發布的MOD13A3數據集中的月度NDVI柵格數據&#xff08;可查看之前的文章獲悉詳情&#xff09;計算得出。很多小伙伴拿到數據后反饋是否可以處理出…

【負載均衡系列】HAProxy

HAProxy(High Availability Proxy)是一款高性能的 ?TCP/HTTP 負載均衡器,專注于提供高可用性、靈活性和可靠性。以下是關于HAProxy的詳細解析,涵蓋其工作原理、工作機制、工作模式等核心方面: 一、HAProxy 工作原理 HAProxy的核心職責是將客戶端請求高效、可靠地分發到后…

輕松遷移 Elasticsearch 數據:如何將自建索引導出并導入到另一個實例

概述 在日常的 Elasticsearch 運維和數據管理中&#xff0c;數據遷移是一個常見的需求。無論是為了備份、升級&#xff0c;還是將數據從一個集群遷移到另一個集群&#xff0c;導出和導入索引數據都是至關重要的操作。本文將詳細介紹如何將自建 Elasticsearch 實例中的索引數據…

JVM 類加載器之間的層次關系,以及類加載的委托機制

JVM 類加載器之間存在一種層次關系&#xff0c;通常被稱為雙親委派模型 (Parent Delegation Model)。這種層次關系和委托機制是 Java 類加載機制的核心&#xff0c;對于保證 Java 程序的安全性和避免類沖突至關重要。 1. 類加載器的層次關系: JVM 中的類加載器&#xff08;Cl…

基于 Vue 3 的PDF和Excel導出

以下是基于 Vue 3 Composition API 的完整實現&#xff0c;包括 PDF 和 Excel 導出。 一、PDF 導出 (Vue 3) 安裝依賴 在項目中安裝相關庫&#xff1a; npm install html2canvas jspdf Vue 3 代碼實現 <template><div><div ref"pdfContent" cla…

【Jupyter】notebook無法顯示tqdm進度條

錯誤描述 from tqdm.notebook import tqdm 用的時候報錯&#xff1a; Error displaying widget解決方式 # 先裝nodejs conda install -c conda-forge nodejs20# 重裝ipywidgets pip uninstall ipywidgets pip install ipywidgets jupyter labextension install jupyter-wid…

ubuntu20如何升級nginx到最新版本(其它版本大概率也可以)

前言&#xff1a; Nginx非常常用&#xff0c;所以在網絡安全方面備受“關注”。其漏洞非常多&#xff0c;要經常保持軟件更新版本才能更好的保證安全。但是Ubuntu官網適配nginx非常慢&#xff0c;所以nginx官方也會推出針對主流Linux操作系統的包管理工具安裝方式。 步驟&…

word插入Mathtype公式居中和自動更新

word插入公式自動更新 前提&#xff1a;安裝Mathtype 1.word中查看頁的寬度 出現如下 2.設置樣式 出現這個窗口 給樣式隨便起個名字 3.修改樣式 3.1 設置兩個制表位 第二個 3.2 修改公式字體 如下所示 4. 修改公式格式 4.1在word中打開 Mathtype 4.2 修改公式的格式 變成…

如何從后端實現頁面跳轉?

例&#xff1a;請求轉發 例&#xff1a;重定向 例&#xff1a;區別&#xff1a;攜帶參數的后端跳轉 例&#xff1a;是否可以訪問外部資源 請求轉發&#xff1a;客戶端發起一個請求到服務端&#xff0c;服務端把這個請求轉發至其他地方 重定向&#xff1a;客戶端發起一個請求…

APIJSON快速入門

作者 版本 時間 內容 備注 Allen V1.0.0 2021/08/19 初稿完成 AllenV1.0.1 2021/08/22 添加常見問題 1.流程說明 一個接口的開發,比如Java用SpringBoot,Mybatis來開發一般來說就像下面這個流程 部署上這個項目后,流程變成了這樣 如果使用 apijson-framework,還可進一步簡化…

STM32八股【3】------RAM和片上FLASH

1、RAM和FLASH構成 1.RAM ┌──────────────────────────┐ │ 棧區 (Stack) │ ← 從RAM頂端向下擴展&#xff08;存儲局部變量、函數調用信息&#xff09; │--------------------------│ │ 堆區 (Heap) │ ← …

基于springboot的星之語明星周邊產品銷售網站(050)

摘要 隨著信息互聯網信息的飛速發展&#xff0c;無紙化作業變成了一種趨勢&#xff0c;針對這個問題開發一個專門適應洗衣店業務新的交流形式的網站。本文介紹了星之語明星周邊產品銷售網站的開發全過程。通過分析企業對于星之語明星周邊產品銷售網站的需求&#xff0c;創建了一…

Android Launcher3 HotSeat文件夾創建禁止方案全解析

一、技術背景與實現原理 在Android 13 Launcher3定制開發中&#xff0c;需屏蔽HotSeat區域的文件夾創建功能。該功能涉及的核心事件處理流程如下&#xff1a; 復制 [拖拽事件] -> [Workspace.onDrop()] -> [CellLayout.performReorder()]└─> [createUserFolderIf…