用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. 使用tk.mybatis快速开发curd

    使用mybatis已经是可以快速开发程序了,对于单表的curd似乎是一种可抽象的结果,下面介绍tk.mybatis的使用方式. maven引用 我使用的是这个版本,所以相关功能介绍也是这个版本. 使用 ...

  2. Java入门:零碎的知识点

    实例变量经常被称为属性 成员变量和局部变量:前者在类中定义,后者在类的方法中定义且系统不会自动赋初始值 我们创建一个对象的时候实际上执行的是无参的构造方法 静态变量 static String arr ...

  3. 创意时钟 人形时钟 可惜不是 https

    ; (function () { $('#header').css({ 'position':'relative' }).prepend('<div id="clockWrap&quo ...

  4. 家里各台机器的php性能测试

    所用脚本: <?php $before = microtime(true); $list= array( "keya" => "the value a&quo ...

  5. English trip -- VC(情景课)8 C

    MP review: 音标(Phonetic symbol) [ɪ]    lit adj. 照亮的,点着的(light的过去式及过去分词)n. (Lit)人名:(瑞典)利特:(老)李 [ʊ]   g ...

  6. English trip -- Iris老师整理的一般时态

    一般疑问句: 用Yes/No 就能回答的问句. a.g Are you an office worker? 问句 <                                        ...

  7. Spring Cloud常用组件介绍

    一.Eureka (Netfix下) 云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移. 二.Spring Cloud Config (Spring下) 配置 ...

  8. 3-19(晚) require_relative 和 require. === operator的解释。

    kernel#require_relative Ruby tries to load the library named string relative to the requiring file's ...

  9. 页面title改变浏览器兼容性问题

    前一阵子客户在界面上改了下小小的需求,需要点不同的文章title显示不同的模块名称(之前没有区分,统一叫新闻图片),很简单的一个需求但是测试的时候并没有注意到不兼容IE7和IE8.在客户那被尴尬的发现 ...

  10. 我的Java学习笔记-语法

    Java的语法与C#的语法基本都一样,毕竟都是面向对象编程语言.下面记录下Java独有的和我在C#中学习不熟的语法知识 一.Java是解释型语言 二.Java修饰符 1. 访问控制修饰符 defaul ...