用XML做的Unity NPC对话系统


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

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

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



游戏效果:


1

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

注意路径:

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

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

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

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

<?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

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

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下即可!

附:Chinar的GitHub工程案例


END

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


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


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

Unity 3D游戏-NPC对话系统With XML的更多相关文章

  1. Unity 3D游戏开发学习路线(方法篇)

    Unity 3D本来是由德国的一些苹果粉丝开发的一款游戏引擎,一直只能用于Mac平台,所以一直不被业外人士所知晓.但是后来也推出了2.5版,同时发布了PC版本,并将其发布方向拓展到手持移动设备.Uni ...

  2. 《Unity 3D游戏客户端基础框架》概述

    框架概述: 做了那么久的业务开发,也做了一年多的核心战斗开发,最近想着自己倒腾一套游戏框架,当然暂不涉及核心玩法类型和战斗框架,核心战斗的设计要根据具体的游戏类型而定制,这里只是一些通用的基础系统的框 ...

  3. Unity 3D 游戏上线之后的流水总结

    原地址:http://tieba.baidu.com/p/2817057297?pn=1 首先.unity 灯光烘焙 :Unity 3D FBX模型导入.选项Model 不导入资源球.Rig 不导入骨 ...

  4. Unity 3D游戏开发引擎:最火的插件推荐

    摘要:为了帮助使用Unity引擎的开发人员制作更完美的游戏.我们精心挑选了十款相关开发插件和工具.它们是:2D Toolkit.NGUI.Playmaker.EasyTouch & EasyJ ...

  5. Unity 3d游戏逆向及.NET Reflector工具使用介绍

    移动平台游戏框架主要有unity 3d和cocos 2d.我们首先得识别游戏使用的框架.识别Unity游戏Android平台的apk包可以直接解压,看是否有./assets/bin/Data/Mana ...

  6. 【Unity】1.0 第1章 Unity—3D游戏开发和虚拟现实应用开发的首选

    分类:Unity.C#.VS2015 创建日期:2016-03-23 一.简介 Unity是跨平台2D.3D游戏和虚拟现实高级应用程序的专业开发引擎,是由Unity Technologies公司研制的 ...

  7. 【Unity 3D 游戏开发】Unity3D 入门 - 工作区域介绍 与 入门示例

    一. 工作区域详解 1. Scence视图 (场景设计面板) scence视图简介 : 展示创建的游戏对象, 可以对所有的游戏对象进行 移动, 操作 和 放置; -- 示例 : 创建一个球体, 控制摄 ...

  8. Unity 3D游戏-消消乐(三消类)教程和源码

    Unity 消消乐教程和源码 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Start Game -- ...

  9. Unity 3D游戏-见缝插针源码

    Unity见缝插针功能实现 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Sphere Rotatio ...

随机推荐

  1. 【转】libxml2 如何获得某个节点的所有信息

    网址:http://bbs.csdn.net/topics/380115580 顶楼: 我的需求是这样的,我使用libxml2从内存中解析一个xml文件,需要修改某个节点下的一个子节点,修改完成之后, ...

  2. Docker 容器十诫

    [编者按]本文作者为 Rafael Benevides,主要介绍使用 Docker 容器时应该注意的十个陷阱. Docker 容器十诫 当你刚开始使用容器时,会发现容器能解决许多问题,而且好处很多: ...

  3. R-FCN论文理解

    一.R-FCN初探 1. R-FCN贡献 提出Position-sensitive score maps来解决目标检测的位置敏感性问题: 区域为基础的,全卷积网络的二阶段目标检测框架: 比Faster ...

  4. angular5 ng-bootstrap和ngx-bootstrap区别

    https://angular.cn/resources ngx-bootstrap 安装: npm install ngx-bootstrap --save 再引入css <link href ...

  5. C#实现在应用程序间发送消息的方法示例

    本文实例讲述了C#实现在应用程序间发送消息的方法.分享给大家供大家参考,具体如下: 首先建立两个C#应用程序项目. 第一个项目包含一个Windows Form(Form1),在Form1上有一个But ...

  6. FASTQ 数据质量统计工具

    主流工具: FastQC fqcheck readfq 拿到测序数据的第一步就是做质量控制 fqcheck之后得到的结果: 它会统计每条reads,按read 1-100位点计算每个位置的ACGTN含 ...

  7. English trip -- VC(情景课)10 C I like to watch TV. 我爱看电视

    Grammar focus 语法点: like to do    you do    they What  does  he    like to do? does  she Practice 练习 ...

  8. LeetCode--217--存在重复元素

    问题描述: 给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1] 输出 ...

  9. hdu-4289 最大流Dinic模板题

    拆点,套模板. 详情见代码. // // main.cpp // hdu_4289 // // Created by Luke on 16/8/29. // Copyright © 2016年 Luk ...

  10. CCF 2015-03-4 网络延时

    题目:http://115.28.138.223/view.page?gpid=T24 题意就是让求树上的任意两个节点间的距离的最大值.就是树的直径. 首先树的直径模板转载自http://www.07 ...