TimeLine实现简易NPC对话

效果




读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()
    {

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值