zoukankan      html  css  js  c++  java
  • Unity 3D游戏-NPC对话系统With XML

    用XML做的Unity NPC对话系统


    本文提供全流程,中文翻译。

    Chinar坚持将简单的生活方式,带给世人!

    (拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)




    游戏效果:

    这里写图片描述


    1

    Create XML Document —— 创建所需的XML文档


    注意路径:

    我的XML文档”Dialog.xml”放在了 Assets 目录下创建的一个 Data 目录中

    如果名字不一样,需要改名

    这里写图片描述

    或者直接修改解析XML代码中的读取路径,为你自己的路径

    document.Load(Application.dataPath + "/Data/Dialog.xml"); //加载 XML 内容

    举个栗子88

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Dialog System ; Background ; Image ; Music -->
    <root>
      <bg>背景1</bg>
      <bgm>雨声</bgm>
      <say>
        <name>船长</name>
        <image>曲境一号船长1</image>
        <sound>花痴诗1</sound>
        <content>我的小鱼你醒了,还记认识早晨吗?</content>
      </say>
      <say>
        <name>秀秀</name>
        <image>秀秀1</image>
        <sound>花痴诗2</sound>
        <content>昨夜你曾经说, 愿夜幕永不开启。</content>
      </say>
      <say>
        <name>船长</name>
        <image>曲境一号船长2</image>
        <sound>花痴诗3</sound>
        <content>你的香腮边轻轻滑落的</content>
      </say>
      <say>
        <name>秀秀</name>
        <image>秀秀2</image>
        <sound>花痴诗4</sound>
        <content>是你的泪,还是我的泪?</content>
      </say>
      <bg>背景2</bg>
      <say>
        <name>秀秀</name>
        <image>秀秀3</image>
        <sound>花痴诗5</sound>
        <content>初吻吻别的那个季节</content>
      </say>
      <say>
        <name>船长</name>
        <image>曲境一号船长3</image>
        <sound>花痴诗6</sound>
        <content>不是已经哭过了吗?</content>
      </say>
      <bg>背景3</bg>
      <say>
        <name>船长</name>
        <image>曲境一号船长4</image>
        <sound>花痴诗7</sound>
        <content>我的指尖还记忆着</content>
      </say>
      <say>
        <name>秀秀</name>
        <image>秀秀4</image>
        <sound>花痴诗8</sound>
        <content>你慌乱的心跳</content>
      </say>
      <say>
        <name>船长</name>
        <image>曲境一号船长1</image>
        <sound>花痴诗9</sound>
        <content>温润的体香里</content>
      </say>
      <bg>背景4</bg>
      <say>
        <name>秀秀</name>
        <image>秀秀1</image>
        <sound>花痴诗10</sound>
        <content>那一缕长发飘飘…</content>
      </say>
    </root>

    2

    Audio Manager —— 音频管理器脚本


    将此脚本挂在保证激活状态的 GameObject 上,并添加 2 AudioSource 组件

    通过拖动的方式

    Inspecter 面板中将 2 AudioSource 组件拖到 ↓

    背景音: BgmAudioSource 和音效: SeAudioSource 框中

    代码直接 Copy

    举个栗子88

    using UnityEngine;
    
    
    /// <summary>
    /// 声音管理类
    /// </summary>
    public class AudioManager : MonoBehaviour
    {
        public static AudioManager Instance;       //单例
        public        AudioSource  BgmAudioSource; //背景音
        public        AudioSource  SeAudioSource;  //音效
        private       AudioClip    _clip;          //音乐文件
    
    
        /// <summary>
        /// 初始化函数
        /// </summary>
        void Start()
        {
            Instance = this;
        }
    
    
        /// <summary>
        /// 播放背景音
        /// </summary>
        public void PlayBgm(string inName)
        {
            _clip               = Resources.Load<AudioClip>(inName); //加载音乐文件
            BgmAudioSource.clip = _clip;                             //更换音乐文件为Clip默认文件
            BgmAudioSource.Play();                                   //播放音乐
        }
    
    
        /// <summary>
        /// 播放音效
        /// </summary>
        public void PlaySe(string inName)
        {
            _clip = Resources.Load<AudioClip>(inName); //加载音乐文件
            SeAudioSource.PlayOneShot(_clip);          //播放音效,一声就完了
        }
    
    
        /// <summary>
        /// 停止背景音
        /// </summary>
        public void StopBgm()
        {
            BgmAudioSource.Stop(); //停止播放器
        }
    }

    这里写图片描述


    3

    UI Manager —— 界面交互控制


    将此脚本挂在保证激活状态的 GameObject

    通过拖动的方式

    Inspecter —— 面板中:分别添加声明的 6 个对象

    代码直接 Copy

    举个栗子88

    using UnityEngine;
    using System.Xml;                  //引用XML
    using UnityEngine.UI;              //引用UI
    using System.Collections.Generic;  //引用集合
    using UnityEngine.SceneManagement; //引用命名空间
    
    
    
    /// <summary>
    /// 枚举指令类型
    /// </summary>
    public enum CommandType
    {
        Say, //说话
        Bgm, //背景音
        Bg   //背景
    }
    
    
    
    /// <summary>
    /// 基类:指令类
    /// </summary>
    public class Command
    {
        public CommandType AllType; //定义成员变量 类型对象
    }
    
    
    
    /// <summary>
    /// 说话指令类:继承 指令基类
    /// </summary>
    public class Say : Command
    {
        public string Name;    //名字
        public string Image;   //图片
        public string Sound;   //音乐
        public string Content; //内容
    }
    
    
    
    /// <summary>
    /// 背景音指令类:继承 指令基类
    /// </summary>
    public class Bgm : Command
    {
        public string Name; //名字
    }
    
    
    
    /// <summary>
    /// 背景指令类:继承 指令基类
    /// </summary>
    public class Bg : Command
    {
        public string Name; //名字
    }
    
    
    
    /// <summary>
    /// 对话系统
    /// </summary>
    public class DialogUI : MonoBehaviour
    {
        public  List<Command> Commands = new List<Command>(); //声明一个 List 数组 类型为:Command
        private int           _index   = 0;                   //默认索引为0
        public  GameObject    GameImage;                      //游戏界面
        public  GameObject    ReloadBut;                      //重开按钮
        public  Image         BgImage;                        //背景图
        public  Image         HeadPortrait;                   //头像
        public  Text          NameText;                       //名字文本
        public  Text          ConttentText;                   //内容文本
        private bool          _isExecute = false;             //是否执行命令:默认不执行
    
    
        /// <summary>
        /// 初始化方法
        /// </summary>
        void Start()
        {
            AnalysisXml();                                                                            //调用解析XML方法
            GameObject.Find("StartGameButton").GetComponent<Button>().onClick.AddListener(StartGame); //给开始游戏按钮,添加监听事件
        }
    
    
        /// <summary>
        /// 更新函数
        /// </summary>
        void Update()
        {
            if (Input.GetMouseButtonDown(0)           && _isExecute == true ||
                Input.GetKeyDown(KeyCode.KeypadEnter) && _isExecute == true) //如果按下鼠标左键或者按下Enter
            {
                OneByOneExecuteCommand(); //执行对话命令函数
            }
        }
    
    
        /// <summary>
        /// 开始游戏
        /// </summary>
        public void StartGame()
        {
            GameImage.SetActive(true); //激活游戏界面
            _isExecute = true;         //游戏开始:可以开始执行代码
            OneByOneExecuteCommand();  //游戏页面被激活的时候,就执行一次
        }
    
    
        /// <summary>
        /// 执行对话命令函数
        /// </summary>
        public void OneByOneExecuteCommand()
        {
            if (_index >= Commands.Count) //下标越界:读完
            {
                ReloadBut.SetActive(true);                                         //激活重载按钮
                ReloadBut.GetComponent<Button>().onClick.AddListener(ReloadScene); //给按钮添加 重载场景 监听事件
                _isExecute = false;                                                //关闭执行命令
                return;
            }
    
            Command command = Commands[_index++]; //自增:取出一条命令
    
            switch (command.AllType)
            {
                //如果类型是:Say 说话
                case CommandType.Say:
                    Say say             = (Say) command;                     //实例化 Say 对象 say
                    HeadPortrait.sprite = Resources.Load<Sprite>(say.Image); //更换头像
                    NameText.text       = say.Name;                          //人物
                    ConttentText.text   = say.Content;                       //说话内容
                    if (!string.IsNullOrEmpty(say.Sound))                    //如果音效名不为空
                    {
                        AudioManager.Instance.PlaySe(say.Sound); //播放音效
                    }
                    break;
    
                //如果类型是:Bgm 背景音乐
                case CommandType.Bgm:
                    Bgm bgm = (Bgm) command;                 //实例化 Bgm 对象 bgm
                    AudioManager.Instance.PlayBgm(bgm.Name); //播放背景音乐
                    OneByOneExecuteCommand();                //直接执行下一条
                    break;
    
                //如果类型是:Bg 背景
                case CommandType.Bg:
                    Bg bg          = (Bg) command;                    //实例化 Bg 对象 bg
                    BgImage.sprite = Resources.Load<Sprite>(bg.Name); //更换背景图片
                    OneByOneExecuteCommand();                         //直接执行下一条
                    break;
            }
        }
    
    
        /// <summary>
        /// 重载场景
        /// </summary>
        public void ReloadScene()
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); //重载当前场景
        }
    
    
        /// <summary>
        /// 解析XML
        /// </summary>
        private void AnalysisXml()
        {
            XmlDocument document = new XmlDocument();                 //实例化一个xml文档
            document.Load(Application.dataPath + "/Data/Dialog.xml"); //加载 XML 内容
            XmlElement rootEle = document.LastChild as XmlElement;    //根节点
            foreach (XmlElement ele in rootEle.ChildNodes)            //遍历根节点的所有子节点
            {
                if (ele.Name == "bgm") //如果元素的名字是XML文档中的节点"bgm"
                {
                    Bgm bgm     = new Bgm();
                    bgm.AllType = CommandType.Bgm;
                    bgm.Name    = ele.InnerText;
                    Commands.Add(bgm); //添加到命令数组 Commands 中
                }
                else if (ele.Name == "bg")
                {
                    Bg bg      = new Bg();
                    bg.AllType = CommandType.Bg;
                    bg.Name    = ele.InnerText;
                    Commands.Add(bg);
                }
                else if (ele.Name == "say")
                {
                    Say say     = new Say();
                    say.AllType = CommandType.Say;
                    say.Name    = ele.ChildNodes[0].InnerText;
                    say.Image   = ele.ChildNodes[1].InnerText;
                    say.Sound   = ele.ChildNodes[2].InnerText;
                    say.Content = ele.ChildNodes[3].InnerText;
                    Commands.Add(say);
                }
            }
        }
    }

    这里写图片描述


    4

    Finish —— 测试运行


    直接点击运行 Or Alt+P

    Chinar所作,Down下即可!

    举个栗子88 附:Chinar的GitHub工程案例

    这里写图片描述


    END

    本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

    对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

    对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

  • 相关阅读:
    Ueditor富文本编辑器
    ashx误删后,未能创建类型
    一个菜鸟的ASP.NET观光路线图
    地位尴尬的WebForm、ASP.NET核心知识(10)
    经典排序算法--归并排序
    经典排序算法--快速排序
    经典排序算法--冒泡排序
    经典排序算法--堆排序
    经典排序算法--简单选择排序
    经典排序算法--希尔排序
  • 原文地址:https://www.cnblogs.com/chinarbolg/p/9601471.html
Copyright © 2011-2022 走看看