美文网首页
TimeLine实现简易NPC对话

TimeLine实现简易NPC对话

作者: 神大人korose | 来源:发表于2022-07-06 11:18 被阅读0次
    效果 NPC读表对话演示.gif
    对话表
    TimeLine设置

    读Excel表使用EPPlus.dll和Excel.dll两个库
    读Excel表脚本如下,使用

    using OfficeOpenXml;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    
    public static class ExcelManger
    {
        public static string sPath = Application.streamingAssetsPath + "/";
        static string sheetName = "Sheet1";
        public static List<List<string>> Read(string path)
        {
            List<List<string>> list = new List<List<string>>();
            FileInfo excelName = new FileInfo(sPath + path + ".xlsx");
            using (ExcelPackage package = new ExcelPackage(excelName))
            {
                ExcelWorksheet worksheet = package.Workbook.Worksheets[sheetName];
                int start = worksheet.Dimension.Start.Row;
                int end = worksheet.Dimension.End.Row + 1;
                int num = 1;
                for (int i = start; i < end; i++)
                {
                    if (i == start)
                    {
                        while (worksheet.Cells[i, num].Text != "")
                        {
                            Debug.Log(worksheet.Cells[i, num].Text);
                            num++;
                        }
                    }
                    else
                    {
                        List<string> strs = new List<string>();
                        for (int j = 1; j < num; j++)
                        {
                            strs.Add(worksheet.Cells[i, j].Text);
                        }
                        list.Add(strs);
                    }
                }
                return list;
            }
        }
    }
    

    读表数据结构如下

    
    //npc对话表
    class Chat
    {
        public string chatid;//对话id
        public string npcid;//npcid
        public string chatContent;//聊天内容
        public string[] selet;//聊天选项
        public string[] follow;//选项后续
        public string[] followChatid;//后续对话id
        public string[] followOpenid;//后续打开id
        //构造函数
        public Chat(params string[] strs)
        {
            this.chatid = strs[0];
            this.npcid = strs[1];
            this.chatContent = strs[2];
            this.selet = strs[3].Split('|');
            this.follow = strs[4].Split('|');
            this.followChatid = strs[5].Split('|');
            this.followOpenid = strs[6].Split('|');
        }
    }
    

    基本逻辑脚本

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.Playables;
    using UnityEngine.Timeline;
    
    public class NPC_0 : MonoBehaviour,ITimeControl
    {
        Dictionary<string, Chat> npcChat = new Dictionary<string, Chat>();
        public PlayableDirector director;//Timeline导演
        public Text nick;//对话框昵称显示
        public Text chat;//对话框聊天内容显示
        public Button button;//对话框按钮
        public Transform selectBox;//对话框选项按钮框
    
        string npcid = "0";//当前npcid
        string chatid = null;//当前对话id
    
        string one = null;//初始对话id
    
        void Start()
        {
            //读表
            List<List<string>> list = ExcelManger.Read("NPC_Chat");
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i][1] == npcid.ToString())//只保存当前npc的对话
                {
                    npcChat.Add(list[i][0], new Chat(list[i].ToArray()));
                    //默认第一条
                    if (one == null)
                    {
                        one = list[i][0];
                    }
                }
            }
            //随机npc坐标
            float x = Random.Range(-10, 10);
            float z = Random.Range(-10, 10);
            float y = Mathf.PerlinNoise(x * 0.2f, z * 0.2f) * 5 - 5;
            transform.position = new Vector3(x, y, z);
    
        }
        public void OnSignal_0()
        {
            //暂停
            director.Pause();
            //判断是否拥有对话选项
            if (npcChat[chatid].selet[0] == "")
            {
                //没有对话选项,将对话按钮变为结束按钮
                button.onClick.RemoveAllListeners();
                button.onClick.AddListener(() =>
                {
                    director.time = 0;
                    //关闭对话框
                    chat.transform.parent.gameObject.SetActive(false);
                    //打开玩家摄像头
                    UserData.cmfl.gameObject.SetActive(true);
                });
            }
            else
            {
                //有对话选项,循环创建选项按钮
                for (int i = 0; i < npcChat[chatid].selet.Length; i++)
                {
                    GameObject btn = Instantiate(Resources.Load<GameObject>("Button"), selectBox);
                    //按钮的名字换成选项内容
                    btn.GetComponentInChildren<Text>().text = npcChat[chatid].selet[i];
                    //注意闭包
                    int ii = i;
                    btn.GetComponent<Button>().onClick.AddListener(() =>
                    {
                        //点击按钮时判断后续类型
                        if (npcChat[chatid].follow[ii] == "0")//继续下一段对话
                        {
                            //将对话id改为指定的下一段对话id
                            chatid = npcChat[chatid].followChatid[ii];
                            //重新播放TimeLine
                            director.time = 1;
                            director.Play();
                        }
                        else if (npcChat[chatid].follow[ii] == "1")//打开界面
                        {
                            //继续播放
                            director.Play();
                        }
                        else if(npcChat[chatid].follow[ii] == "2")//直接结束
                        {
                            director.time = 0;
                            chat.transform.parent.gameObject.SetActive(false);
                            UserData.cmfl.gameObject.SetActive(true);
                        }
                        //每次点击按钮后删除所有按钮(可以使用对象池重复利用)
                        for (int i = 0; i < selectBox.childCount; i++)
                        {
                            Destroy(selectBox.GetChild(i).gameObject);
                        }
                    });
                }
            }
        }
        public void OnSignal_1()
        {
            //此处应读打开表,打开相应的功能
            Instantiate(Resources.Load<GameObject>("Shop"), GameObject.Find("Canvas").transform);
        }
        private void OnTriggerEnter(Collider other)
        {
            Debug.Log("碰到了");
            if (other.transform.CompareTag("Player"))
            {
                director.time = 0;
                director.Play();
                //关闭玩家摄像机 自动切换到npc摄像机
                UserData.cmfl.gameObject.SetActive(false);
                //设置默认第一条
                chatid = one;
                //对话跳过
                button.onClick.RemoveAllListeners();
                button.onClick.AddListener(() =>
                {
                    if (director.time < 10)
                    {
                        //1秒10个字,最多允许100个字
                        director.time = 10;
                    }
                });
            }
        }
    
        public void SetTime(double time)
        {
            //时间不够输出长度则逐字输出
            if (npcChat[chatid].chatContent.Length >= (int)(director.time * 10))
            {
                chat.text = npcChat[chatid].chatContent.Substring(0, (int)(director.time * 10));
            }
            else if (director.time < 10)//时间超过输出长度则跳过
            {
                director.time = 10;
            }
        }
    
        public void OnControlTimeStart()
        {
            //此处应查npc表输出npc的名字
            nick.text = npcid;
        }
    
        public void OnControlTimeStop()
        {
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:TimeLine实现简易NPC对话

          本文链接:https://www.haomeiwen.com/subject/lhfybrtx.html