一、前言
Dialogue System是一个分支式的统一会话系统。它不需要任何脚本,但它是设计为易于由程序员扩展。
Unity对话系统让你:
- 用分支逻辑编写交互式对话。
- 在灵活的、完全可自定义的UI系统中显示会话。
- 定义玩家要完成的任务/任务。
- 播放镜头序列,如相机剪辑和音频。
- 保存和加载游戏,并在场景更改中持久化数据。
- 使用本地化来显示文本,并在不同的语言中播放剪裁场景。
- 导入和导出各种格式,如:draft、Chat Mapper和CSV。
效果图:
二、下载地址
https://download.csdn.net/download/q764424567/12326896
三、正文
1、开始
设置
如果你的项目使用Unity5.x,则您必首先更改为强制文本序列化
- Edit → Project Settings → Editor
- 然后改变Asset Serialization到Force Text和Version Control到Visible Meta Files
下一步
⑴演示场景
演示场景
演示场景在Plugins ► Pixel Crushers ► Dialogue System ► Demo
播放它,看看对话系统是如何工作的
怎么玩
- 使用箭头键或WASD键移动。
- 用鼠标看。
- 查看可交互对象并按下空格键进行交互。
- 鼠标左键射击。
- 按“ESC”以打开“暂停”菜单。
演示任务
您可以在演示场景中这样做:
- 获取发射代码(任务):与一等兵哈特交谈,以获得这一任务。它涉及到在隔壁房间找到一个密码并与计算机进行交互。
- 敌人进攻(任务):在隔壁的房间里和NPC谈一谈,来完成这个任务。它演示了如何设置基于计数器的任务,在这种情况下是一次杀戮任务。
- 变更场景与门互动以改变场景。这演示了如何在场景更改中保留数据。
- 存载小游戏使用“暂停”菜单保存和加载游戏。
⑵概述
对话制度由以下主要部分组成:
- 对话数据库:包含对话、任务和变量。
- 对话编辑器:编辑对话数据库。您还可以导入和导出第三方格式。
- 对话管理器:在运行时管理对话系统活动。提供预制件。
- 对话UI:显示交互式对话、警报信息、任务日志等。
- 交互系统:在运行时触发活动,例如启动会话。
对话数据库
dialogue database是一个资产文件,包含会话、任务和用户定义的变量。你通常会使用对话编辑器来编辑其内容,尽管您也可以从其他几种格式中导入内容。
对话数据库包含设计时内容,以及在Unity编辑器中编辑的字段。在运行时,对话系统将对话数据库视为只读数据库;它将对话数据库字段加载到游戏期间可以改变值的地方。
对话编辑器
对话管理器
对话管理器是您场景中的一个GameObject,它协调所有的对话系统活动并保存对话系统的运行时数据。
对话UI
对话系统使用以下UI:
- 对话UI:运行交互式对话和警报消息。(如上文所示)
- 任务日志窗口:显示玩家的主动任务和已完成的任务。
- 任务跟踪器HUD:显示主动任务的跟踪信息。
交互系统
对话系统提供与GameObjects交互的组件,并执行诸如开始对话和更新任务状态等操作。
本地化
对话系统支持对话数据库内容和一般UI元素的本地化。
扩展对话系统
虽然对话系统的默认功能非常强大和灵活,但您也可以创建自己的逻辑函数、裁剪场景操作、UI类型等等。这可以在脚本中编写。
⑶快速启动
本节直接跳到使用对话系统创建和运行会话。您将学习如何:
- 创建对话数据库并编写对话。
- 设置对话管理GameObject。
- 开始谈话。
- 与对象交互。
- 在对话期间禁用播放器控制。
步骤:
步骤1.创建一个新场景(File → New Scene).
步骤2.拖动预制件Assets ► Plugins ► Pixel Crushers ► Dialogue System ► Prefabs ► Dialogue Manager进入场景:
步骤3.这个GameObject已经指向了一个基本的对话UI,我们需要建立一个对话数据库,让我们单击Create:
步骤4.在为数据库指定好路径以及名字之后,再次点击对话管理器GameObject。单击Edit按钮或对话系统图标。这将打开“对话编辑器”窗口:
步骤5.单击Conversations标签。
- 单击“+”按钮添加新会话。
- 右键单击橙色START节点并选择创建子节点。点击子节点,在Inspector面板的Dialogue Text输入“Hello.”字段
- 右键单击灰色节点(“Hello.”),选择Create Child Node创建子节点,再次输入"Good Bye."
- 灰色节点是NPC说的,蓝色节点是玩家说的。你的谈话应如下所示
步骤6.为玩家创建一个空游戏对象(GameObject → Create Empty)和一个Cube给NPC(GameObject → 3D Object → Cube)。将空游戏对象重命名为“Player”。将Cube重命名为“NPC”,并将其位置设置为(0,0,0),使其在“Game”视图中可见。
步骤7,点击NPC。加一个对话系统触发器:
步骤8.单击Add Action并选择Start Conversation:
步骤9.从Conversation下拉,指定Conversation字段为New Conversation 1,并将Player分配给Conversation Actor,NPC分配给Conversation Conversant.
步骤10.最后,设置Trigger为On Start。这告诉对话系统触发器在场景开始时执行其操作。
第11步,现在开始你的第一次对话!对话系统将显示NPC线(“hello.”)。紧随其后的是Player Response菜单,它包含一个选项(“Goodbye.”)。它使用了基本的标准对话UI,这是一个通用模板,您以后可以定制它来查看您想要的任何内容。
接下来,我们将使用交互系统开始对话。
步骤12.设置Trigger为On Use。这告诉对话系统触发器在接收OnUse消息时执行其操作,通常来自播放器上的交互组件。
步骤13.添加Usable组件。这告诉玩家的交互组件,NPC可被点击的最大使用距离是30
步骤14.点击玩家对象并添加一个Selector组件。设置Select At为Mouse Position:
步骤15.现在再放一遍现场。将鼠标放置在立方体上,以便看到以下黄色消息:
这意味着玩家的选择器组件已经检测到NPC的可用组件。按空格键或鼠标右键。
Selector组件将向NPC发送OnUse消息,NPC的对话系统触发器将通过启动会话来响应。
Selector组件和similar 组件,Proximity Selector组件,提供触发对话系统活动的方法。
它们可定制。您可以将它们配置为选择多种不同的方法,而不仅仅是使用鼠标光标。
使用它们也不是强制性的。
如果你愿意,可以使用自己的交互系统或C#代码运行对话系统触发器。
步骤16.您可能注意到Selector组件在会话期间保持活动状态。
在许多情况下,在交谈期间,您会想要禁用选择器和可能的其他组件,如玩家的运动和相机控制。
这样做的一种方法是添加一个对话系统事件组件。
此组件具有在各种对话系统活动上运行的事件。
配置在谈话开始时禁用选择器和谈话结束要重新启用它:
总结
这个快速启动演示了如何:
- 创建对话数据库并编写对话。
- 设置对话管理GameObject。
- 开始谈话。
- 与对象交互。
- 在对话期间禁用播放器控制。
2、对话编辑器
⑴对话数据库
对话数据库是一个资产文件。若要创建对话数据库,请执行以下操作:
- 单击对话管理的Create按钮。
- 或选择Assets → Create → Pixel Crushers → Dialogue System → Dialogue Database
对话数据库包含以下类别:
类别 | 描述 |
---|---|
Database数据库 | 设置描述、作者和版本,以及数据库范围 |
Actors角色 | 会话参与者(玩家、NPC、交互对象) |
Items/Quests任务系统 | 任务定义 |
Locations位置 | 位置信息 |
Variables变量 | 用户定义的变量来判断对话决策 |
Conversations交谈 | 对话 |
下面就详细的介绍每一个类别
⑵对话编辑窗口
要打开对话编辑器,可以使用菜单项Tools → Pixel Crushers → Dialogue System → Dialogue Editor
或者点击对话管理器的logo横幅,或者双击对话数据库资源。
对话编辑器窗口与Inspector视图一起工作。
⑶Database数据库
Database Properties:
- Author:作者
- Version:版本
- Description:描述
- Global User Script:全局用户脚本,在运行时可以加载数据库设置的Lua代码
- Emphasis Settings:重点设置,可以标注设置颜色值
Global Search & Replace:全局搜索和替换允许您在对话数据库中搜索(可选替换)文本。
Merge Database:允许你将另一个对话数据库的内容合并到当前正在编辑的对话数据库中。
Export Database:允许你将对话数据库导出为各种格式,如voiceover脚本和CSV(电子表格)。
Localization Export/Import:本地化导出/导入foldout允许您以比导出数据库foldout更简单的格式导出本地化CSV文件。
Editor Settings:编辑器设置foldout包含诸如在何处以及如何频繁地对数据库进行自动备份等设置。
⑷Actors角色
Actors选项卡定义对话参与者。
你可以指定参与者的名称(以及在ui中使用的可选显示名称)、可选的人像图像等等。
肖像图像可以是纹理资产或Sprites。
如果你为一个角色使用Sprites,就不要给肖像纹理赋值。
同样的,如果你使用纹理,不要给Sprites赋值。
⑸Quests/Items任务系统
任务/项目选项卡定义任务和项目。项目只是您可以为自己的目的使用的数据记录。对话系统对条目不做任何特殊处理。
任务由任务系统使用,这在任务部分有详细说明。
使用此选项卡定义任务和可选的任务条目(子任务)。
你的任务文本可以包括标记标签。
状态是任务的开始状态。
此值不会在运行时实时更新;相反,在手表选项卡上查看任务的实时状态。
如果你想要任务出现在任务追踪界面,勾选可追踪,并在开始时追踪(任务一激活就会开启追踪)。
⑹Locations位置
位置只是数据记录。对话系统不会对地点做任何特殊的处理。
⑺Variables变量
变量是你可以在游戏中设置和检查的值。使用它们来追踪信息,例如玩家所做的决定,任务所收获或失败的目标数量等。Conversations选项卡和对话系统组件提供下拉菜单来选择变量并检查或设置它们。
对话系统将在对话开始时自动创建和设置四个变量。
你不必将它们添加到数据库中,但是如果你想在对话中方便地在下拉菜单中引用它们,你可以添加它们。
- Actor:对话的主要参与者(通常是玩家)的显示名称。
- Conversant:谈话的主要交谈者(通常是NPC)的显示名。
- ActorIndex:参与者的Actor[]表索引,提供了可选的低级Lua代码。
- ConversantIndex:Actor[]将谈话者的索引放在表中。
如果您的对话将内容分配给内置的变量Alert,对话系统将在对话结束时将其显示为警报消息。您还可以使用逻辑和Lua中描述的ShowAlert() Lua函数。
⑻Conversations对话
这是对话编辑器的核心。
你可以使用节点编辑器(如上所示)创建、编辑和删除对话。
在运行期间,此选项卡显示当前对话的实时视图。
节点编辑器
操作 | 步骤 |
---|---|
Create new conversation 创造新的对话 | 点击对话标题下拉框右边的“+”。 |
Edit conversation properties 编辑会话属性 | 单击空白画布区域。用于设置标题、主要参与者和覆盖对话管理器的显示设置。 |
Add/delete node 添加/删除节点 | 右键单击node的上下文菜单。(添加子节点时,按住Shift键使用相同的actor分配,而不是交换它们。) |
Edit node 编辑节点 | 单击节点。 |
Edit link arrow Edit链接箭头 | 点击链接箭头。 |
Change display settings 更改显示设置 | Use 在右上角使用Menu 菜单 。 |
节点的检查器视图
操作 | 步骤 |
---|---|
ID | 内容ID号 |
Title 标题 | 可选文本仅供参考。没有显示给玩家。 |
Description 描述 | 可选文本仅供参考。没有显示给玩家。 |
Actor 角色 | 说这句台词的角色。 |
Conversant 对话 | 说话人对角色(听众)说话。 |
Group 分组 | 如果勾选此项,则将其标记为用于分组子节点的直通节点。 |
Menu Text 菜单文本 | 在播放器响应菜单中显示的文本,例如对对话文本的简短解释。如果为空,则默认为对话文本。 |
Dialogue Text 对话文本 | 文本显示字幕。如果为空,则默认为菜单文本。注意:您还可以双击某个节点,直接在该节点上输入对话文本。 |
Sequence 序列 | 当角色说出这句台词时播放的过场动画。如果为空,则使用对话管理器的默认序列。 |
Response Menu Sequence 响应菜单序列 | 可选序列播放在后台,而响应菜单是可见的。如果玩家在播放响应菜单序列时在响应菜单中进行选择,则响应菜单序列将结束,下一个对话条目的序列将在同一帧上开始。 |
Conditions 条件 | 条件必须为真,才能允许玩家在响应菜单中说出或显示该行。 |
False Condition Action 错误条件的反应 | 当情况不对时该怎么做。 |
Script 脚本 | 调用节点时要运行的操作。 |
OnExecute() | 当这个节点被调用时运行UnityEvent。 |
Links To 链接 | 使用下拉菜单手动设置链接,调整它们的优先级,并调整它们的顺序。 |
Conditions 条件
你可以使用指向并单击下拉菜单或手动输入来将Lua表达式添加到条件字段,以允许对话仅在Lua表达式为真时才使用该输入。
例如,假设你只希望NPC在玩家访问巴黎时说出一行对话。
您可以定义一个初始值为false的变量“VisitedParis”。
当玩家访问巴黎时,将变量设置为true。然后为NPC的对话条目添加一个条件:
- Dialogue Text: “So, what did you think of Paris?” “那么,你觉得巴黎怎么样?”
- Condition 条件: Variable[“VisitedParis”] == true 变量(“VisitedParis”) = = true
对话提前一层评估条件
对话系统在对话之前对链接进行额外的一级评估。
它必须这样做,以正确处理某些继续按钮模式。
这意味着,如果你在一个节点设置一个值(例如,节点),然后你不能检查它在下一个节点(节点B)因为对话系统将已经检查节点B之前运行节点的条件。
相反,你需要单独用一个空的间隔节点推迟评估的条件。
为了演示这一点,我们将使用抛硬币的对话示例:
在上面的例子中,“抛硬币”节点将变量x随机设置为1或2。我们不能立即使用两个条件节点(“正面”和“反面”)进行跟踪,因为对话系统提前一层评估——这意味着在“抛硬币”节点运行之前,它已经测试了“正面”和“反面”的条件。
为了解决这个问题,我们在对话中添加了一个中间节点,将标题设置为“延迟评估”以提醒我们自己它的用途,并将对话文本留空。
然后我们将序列设置为None(),这样它将立即进入对话的下一个步骤。
如果您使用的是continue按钮,那么在序列字段上选择
“+” → Continue → Simulate continue button click,而不是使用None()。
在处理条件时,将对话管理器的调试级别临时设置为Info可能也有帮助。
这将向控制台窗口添加大量信息。
如果你仔细阅读,你会发现下面这些行是相似的:
Dialogue System: Lua(x = math.random(2)) Dialogue System: Referee says 'Flipping coin...' Dialogue System: Block on False Link (Referee): ID=5:3 'Heads!' Condition='x == 1' Dialogue System: Add Link (Referee): ID=5:4 'Tails!' (True) Dialogue System: Referee says 'Tails!'
第3-4行表示指向’Heads’的链接被阻塞了,因为’x1’是假的,但它正在将链接添加到’Tails’(因为’x==2’为真)。
OnExecute() UnityEvent
事件折叠包含一个名为OnExecute()的UnityEvent。
使用它类似于将事件处理程序添加到Unity UI按钮的OnClick()事件。
但是,由于对话数据库独立于场景而存在,您不能分配场景对象。
相反,您必须分配一个资产文件,例如prefab或ScriptableObject。
注意:UnityEvents不受数据库导出特性或第三方格式导入器的支持。
在下面的示例中,我们将创建一个ScriptableObject资产,它提供了播放音频剪辑的方法。
然后我们将该方法分配给对话条目的OnExecute()事件。
首先,创建一个名为TestScriptableObject的新c#脚本,其中包含以下代码。
TestScriptableObject.cs
using UnityEngine;
[CreateAssetMenu(fileName = "TestScriptableObject")]
public class TestScriptableObject : ScriptableObject
{
public AudioClip[] audioClips;
public void PlayAudioClip(int i)
{
AudioSource.PlayClipAtPoint(audioClips[i], Vector3.zero);
}
}
接下来,在项目视图中选择Create→TestScriptableObject。这将创建一个资产文件:
你可能希望将资产移动到名为Resources的文件夹中。
通过这种方式,它将被包含在构建中。
在Unity的一些版本中,一些平台会剥离它认为不需要的资产。
这种情况通常发生在脚本对象资产中,这些资产在任何场景中都没有被引用。
检查你的新资产文件。你可以分配音频剪辑到它:
最后,检查对话条目节点的OnExecute()事件,单击“+”按钮,并分配TestScriptableObject。选择你想要执行的方法(PlayAudioClip),并指定你想要播放的音频剪辑的索引:
Outline Editor 大纲编辑器
你也可以在大纲模式下编辑对话,如上图所示,这对像Bioware的Aurora工具集这样的编辑器的用户来说可能更熟悉。要切换到大纲模式,选择Menu → Outline
⑼Templates模板
使用Templates选项卡来更改添加到新角色、任务、对话条目等的默认字段。
你还可以更改对话选项卡的大纲模式中使用的颜色。
右上角的菜单允许您保存和加载模板设置,用数据库中已经存在的自定义字段填充模板,并将模板应用于数据库中的所有内容。
若要添加新的自定义字段,请展开要自定义的类别。
然后单击灰色的“+”,提供字段详细信息。
在下面的屏幕截图中,我们为角色添加了一个自定义年龄字段。
我们还选择勾选主复选框,它告诉对话编辑器在actor的主检查器部分显示它,而不只是在所有字段中显示它。
⑽Watches观看
在运行时,一个Watches选项卡将替换Templates选项卡。在这个选项卡中,您可以查看变量、任务和任意Lua表达式的运行时值。您还可以使用窗口底部的代码栏来运行Lua表达式。
⑾使用多个数据库
使用单个对话数据库通常要容易得多。
但是,对话系统支持多个数据库。
您需要对多个数据库进行更多的管理,以跟踪它们,并在适当的时候装入和取出内存,但是它们对于分解您的内容非常有用,既可以用于组织,也可以用于减少在任何给定时间装入内存的内容的数量。
Deciding Between Single Or Multiple Databases 在单个或多个数据库之间进行选择
这里有一些准则,以决定使用一个数据库或多个数据库:
- 一个包含1000个平均长度的对话的对话数据库大约需要15 MB的内存,相当于几个纹理文件。
- 如果你正在制作一个桌面游戏,15 MB应该不是问题。在这种情况下,使用多个数据库的唯一原因是为了您的组织利益。
- 如果您构建的是非常低端的移动设备,15 MB可能太多了,但最终这取决于您的规格和需求。
- 单个数据库比您愿意使用的内存预算大,或者您的数据库有许多不同的元素,您需要对其进行组织拆分。
Sync Assets From Another Database 从另一个数据库同步资产
如果你使用多个对话数据库,你可能想要在一个数据库中定义所有的角色,在另一个数据库中定义所有的任务,等等。
然后可以配置对话数据库,从这些数据库中提取元素。
为此,在选项卡的菜单中从DB中选择Sync。然后选择要同步元素的源数据库。
你可以添加更多的元素,但是请记住,与源数据库中相同ID的元素将被覆盖。
例如,假设你正在编写一款游戏,玩家带着一群伙伴从一个星球旅行到另一个星球。
您可以在源数据库中定义播放器和同伴角色。
然后,您可以为每个从这个源数据库同步的行星创建一个单独的数据库,并将特定的参与者添加到该行星。
Unique ID Tool 惟一的ID的工具
如果您只使用一个对话数据库,您可以跳过此页。
在内部,对话数据库中的每个元素(actor、item、conversation等)都有一个ID号。
在单个数据库中,对于每种类型的元素,这些id通常是惟一的。
但是,在一个数据库中使用的ID也可能在另一个数据库中使用。
如果在运行时加载两个数据库,则id将冲突。
对话系统不会知道你用给定的ID引用了哪个资产。
为了防止这种情况,使用唯一ID工具:Tools → Pixel Crushers → Dialogue System → Tools → Unique ID Tool.
只需添加希望保证惟一id的数据库,然后单击Process。如果您勾选详细日志记录,该工具将在控制台中记录所有ID号更改。
3、对话管理器
对话管理器预制体
对话管理器协调运行时活动并维护包含对话系统运行时数据的Lua环境。添加对话管理器,拖动预制Assets ► Plugins ► Pixel Crushers ► Dialogue System ► Prefabs ► Dialogue Manager
对话管理器的默认设置使其在场景更改时保持不变,并确保场景中只存在一个副本。
您通常会使用一个对话管理器,添加到您的主菜单场景。
你可以在你的外景场景中放置其他对话管理器,这样你就可以在不需要从主场景中进入的情况下测试它们。
但是请记住,在正常的游戏中,主场景中的对话管理器将会执行并摧毁你的位置场景中的“test”对话管理器。
Dialogue System Controller 对话系统控制器
对话系统控制器组件保存对话系统的设置。
Initial Database 最初的数据库
对话管理器在对话数据库启动时加载该对话数据库。
Display Settings 显示设置
显示设置部分包含以下子部分:
- 本地化设置:控制如何处理语言本地化。
- 字幕设置:控制对话UI显示字幕的方式。
- 相机和过场设置:控制过场音序器的工作方式。
- 输入设置:控制玩家响应菜单在对话中的工作方式。
- 警告设置:控制对话UI在屏幕上显示警告消息的方式。
Persistent Data Settings 持久数据设置
持久数据设置部分允许您指定哪些数据包含在已保存的游戏中,以及在场景更改时保存哪些数据。
Other Settings 其他设置
其他设置部分包含其他设置。值得注意的是:
- 实例化数据库:加载对话数据库的副本,而不是直接在Unity编辑器的playmode中使用该资产。
- Dialogue Time Mode 对话的时间模式:默认情况下,对话系统运行Realtime 实时模式,如果你想使用时间刻度,设置对话时间模式GamePlay
- 调试级别:在Unity编辑器的控制台中设置对话系统的日志级别,在构建中设置播放器日志文件。这对于通过对话系统活动进行跟踪非常方便。
Instantiate Prefabs组件
实例化预制块:将基本的UI预制块实例化到对话管理器的画布中。
这些包括选择器元素(参见触发器和交互),以及任务跟踪HUD和任务日志窗口(参见任务)。
你可以分配不同的预制组件来定制游戏的外观。
Input Device Manager组件
输入设备管理器:检测鼠标、操纵杆和键盘控件之间的切换,并帮助UI知道何时自动对焦UI按钮(在操纵杆和键盘模式下),何时不对焦按钮(在鼠标模式下)。
4、触发与交互
本节讲一下如何交互
Dialogue System Trigger对话系统Trigger
对话系统触发组件有三个主要部分:
- 触发Trigger:导致对话系统触发的事件。
- 条件Conditions:对话系统触发执行其动作时必须为真的状态。
- 动作Actions:触发器应该做的事情,比如开始对话或设置任务状态。
Trigger可以设置触发器下拉到这些值:
Trigger触发 | 描述 |
---|---|
On Use 在使用 | 玩家的选择器或接近选择器向GameObject发送一个OnUse消息,或在UnityEvent或脚本中手动调用对话系统触发器的OnUse()方法。 |
On Start 在开始 | 组件启动(例如,在场景启动时)。 |
On Enable 在启用 | 组件已启用。 |
On Disable 在禁用 | 组件被禁用。 |
On Destroy 在摧毁 | 组件被破坏了。 |
On Trigger Enter 在触发输入 | 组件已启用。 |
On Enable 在启用 | 该组件收到了一条OnTriggerEnter消息。要使用这个触发器,组件的GameObject应该有一个触发器碰撞器。你可能需要设置Conditions → Accepted Tags将此触发器限制为带有特定标记(如)的GameObjects Player 。 |
On Trigger Exit 在触发退出 | 组件收到一个OnTriggerExit消息。 |
On Collision Enter 在碰撞输入 | 组件收到了一条OnCollisionEnter消息。 |
On Collision Exit 在碰撞退出 | 组件收到一个OnCollisionExit消息。 |
On Bark Start 在bark上开始 | GameObject开始玩bark游戏(一次性的对白)。 |
On Bark End 在bark结束 | GameObject(游戏物体)完成了对bark的游戏。 |
On Conversation Start 在对话开始 | GameObject只是作为对话的主要参与者。 |
On Conversation End 在谈话结束 | GameObject刚刚结束了对话。 |
On Sequence Start 在序列开始 | GameObject只是作为过场动画序列的主要参与者而开始的。除非您勾选了对话管理器中的对话序列,否则不会调用此事件Subtitle Settings → Inform Sequence Start And End |
On Sequence End 在序列结束 | 刚刚结束了一个序列。 |
Conditions 条件
条件类型 | 描述 |
---|---|
Lua Conditions Lua的条件 | Lua表达式,例如检查变量的值。 |
Quest Conditions 任务条件 | 需要探索。 |
Accepted Tags 接受标签 | 对于OnCollision和OnTrigger事件,另一个GameObject必须有这些标签中的一个。如果接受的标签是空的,所有的游戏对象都是允许的。 |
Accepted GameObjects 接受对象 | 对于OnCollision和OnTrigger事件,另一个GameObject必须在这个列表中。如果接受的gameobject是空的,那么所有的gameobject都是允许的。 |
Action行动
Action行动 | 描述 |
---|---|
Set Quest State 设置任务状态 | 设置任务和/或任务进入状态 |
Run Lua Code 运行Lua代码 | 运行Lua表达式。 |
Play Sequence 播放顺序 | 播放过场动画 |
Show Alert 显示警报 | 通过对话UI显示警告消息。 |
Send Messages 发送消息 | 使用Unity的SendMessage()方法将消息发送到目标。 |
Start Conversation 开始谈话 | 开始一个对话。 |
Set GameObjects Active/Inactive 设置GameObjects活动/活动 | 在整个游戏对象上工作。 |
Set Components Enabled/Disabled 设置启用/禁用组件 | 工作在游戏对象的特定组件。 |
Set Animator States 设置动画状态 | 在GameObjects上设置animator状态。当对话开始时对空闲字符有用。 |
OnExecute() UnityEvent | 允许您使用UnityEvent指定其他操作。 |
Selectors & Usables 选择器和可用
对话系统提供了一个可选的交互系统,可以与带有可用组件的游戏对象(如npc)进行交互。你可以添加两个组件到播放器:
Selector 选择器
选择器组件通过从指定位置(如鼠标位置或屏幕中心)进行光线投射来检测可用项。当玩家按下use按钮时,它会向用户发送一个OnUse消息。
Proximity Selector 距离选择器
接近选择器组件在输入触发器碰撞器时检测可用项。当玩家按下use按钮时,它会向用户发送一个OnUse消息。
OnUse Message 消息
当玩家瞄准一个可用的并按下使用键或使用按钮时,选择器将发送一个OnUse(转换播放器)消息到可用的游戏对象。
对话系统的触发器(如对话系统触发器)响应此消息。
您自己的脚本也可以通过添加OnUse方法来响应这条消息,例如:
void OnUse(Transform player)
{
Debug.Log("I'm being used by " + player);
}
4、对话UI
Dialogue UI
本章解释了如何建立对话用户界面和用户界面。
对话系统使用对话ui来显示交互式对话和屏幕上的警报消息。
您可以通过添加一个对话参与者组件来定制每个参与者在ui中的显示方式。
Standard Dialogue UI 标准对话界面
标准对话UI是一组组件,用于管理上面屏幕快照中显示的UI元素。这些元素是:
- 警告面板:显示警告消息。
- 字幕面板:显示演员的对话文本。
- 响应菜单:显示玩家可以选择的响应。
- 计时器:如果对话管理器配置为定时响应菜单,则显示倒计时。
- 文本输入:从播放器中读取文本输入。
所有的UI元素都可以重新定位和调整。
Standard Dialogue UI Prefabs 标准对话UI预制件
最简单的方法是为对话管理器的对话UI字段分配一个预制块。位于Prefabs ► Standard UI Prefabs模板为:
- Basic:上面显示的默认UI。
- Bubble:显示字幕面板和响应菜单的卡通气泡上方的角色
- Focus:每行的说话者淡出,而另一个行动者淡出到50%的透明度。
- Letterbox:电影风格的字幕,在屏幕的顶部和底部有黑色的条。
- VN:传统的视觉小说布局与较大的肖像图像上方的字幕/菜单框。
- WRPG:带有滚动对话日志的传统西方RPG布局。
Subtitle Panels & Menu Panels 字幕面板和菜单面板
一个标准的对话UI通常有一个或多个字幕面板和菜单面板。
将字幕面板分配给字幕面板列表。
设置NPC默认字幕面板和PC默认字幕面板,指定NPC和玩家默认使用哪些面板。
拥有对话Actor组件的Actor可以指定使用与默认面板不同的面板。
如果在开始对话时允许打开字幕面板为真,对话系统将检查所有对话参与者以识别他们的字幕面板。
如果任何这些副标题面板指定它们应该在对话开始时立即打开,它就会打开它们。
如果你知道对话开始时没有任何面板被配置为打开,则可以取消此复选框以绕过该复选框。
将菜单面板分配给菜单面板列表。将默认菜单面板设置为默认菜单面板。
通常,您将只有一个菜单面板。
在大多数情况下,你将分配与对话UI位于同一画布中的字幕面板和菜单面板。
然而,分配位于不同画布上的面板是可以的。
Subtitle Panel 字幕面板
Menu Panel 菜单面板
Panel Animation 动画面板
字幕面板和菜单面板可以在状态改变时播放动画。
要分配动画,请向面板添加Animator组件。
指定一个动画控制器,该控制器具有以下一种或多种状态的触发器。
下面的列表描述了设置每个触发器的时间:
- Show: 当面板打开时。
- Hide: 当面板关闭时。
- Focus: 当面板正在积极显示对话文本/菜单的当前行时。
- Unfocus: 当面板仍然可见,但不包括当前活动的面板时。
5、逻辑&Lua
对话系统中不需要脚本。
但是,对话系统提供了一种名为Lua的通用脚本语言,它提供了一种非常强大的方法来控制对话流、检查和更改任务状态等等。
在大多数情况下,您可以使用简单的单击菜单。
对话系统使用了Chat Mapper建立的数据模型,Chat Mapper是行业内常用的另一种专业对话创作工具。关于所有参与者、项、位置、变量和对话的信息都存储在Lua表中。
您可以通过指定Lua条件和脚本来控制对话,通常是通过使用指向和单击菜单。
对于那些感兴趣的人,聊天映射器手册有更多关于Lua和对话系统使用的表的背景信息,在标题为用Lua编写脚本的部分。
对话系统中Lua用在哪里
在运行时,对话系统将您的对话数据库视为只读的。它将数据库值加载到Lua中,在Lua中可以检查和更改当前值。
您可以在对话系统的以下区域使用Lua:
- 对话条目中的条件和脚本字段。
- 在[lua(代码)]标签内的对话条目和任务字段的文本(见标记标签)。
- 对话系统触发
- 在您自己的脚本中,使用Lua和/或DialogueLua类(参见如何在您的c#脚本中使用Lua)
- 对话编辑器的手表选项卡和游戏中的Lua控制台组件。
Point-and-Click Lua
在大多数您可以手动输入Lua代码的地方(如果您愿意),您还可以单击a '…按钮将字段切换为点击模式。在这种模式下,你可以使用下拉菜单,而不需要输入任何代码:
点击“+”添加新的条件或动作。点击恢复取消或应用应用您的选择,这将关闭下拉菜单,并为您编写Lua代码:
如何编写Lua代码
如果你喜欢直接写Lua代码,你会发现它类似于c#或UnityScript。有关Lua的更多信息,请参见www.lua.org。
6、动画序列
序列和对话条目
在对话系统中,每一行对话都可以绑定到一个过场动画序列——例如,播放动画、音频文件和/或移动摄像机。此序列在对话条目的序列字段中指定,如果对话条目的序列字段为空,则在对话管理器的默认序列中指定。
在进行对话时,对话系统将在对话序列的持续时间内显示对话条目的对话文本。例如,如果序列运行5秒,对话文本将作为副标题显示5秒。
如何编写序列
场景序列是用简单的基于文本的命令定义的,这使得它们非常紧凑,可以在编写对话时快速添加,甚至可以使用外部创作程序,如聊天映射器和articy:draft。
已经包含了一个很大的音序器命令库,您可以轻松地添加自己的命令。
内置音序器命令的完整列表在音序器命令引用中。
在大多数情况下,如果不想手动输入命令,就不需要这样做。
如果您不想在文本字符串中指定序列,您可以使用交互式编辑器(如Unity Timeline),并使用提供的Timeline() sequalizer命令简单地运行时间轴。
Using Camera Angles 使用相机的角度
您按顺序使用相机(x)命令时,它首先检查相机角度预置。如果它找到一个名称与x匹配的子对象,它将使用该子对象从摄像机角度预置的偏移量。然后,它将摄像机置于与角色相同的偏移位置。
示例:默认的相机角度预置有一个名为close - up的子组件,它大约是向上2个单元,向后1个单元。音序器命令相机(特写)将相机向上移动大约2个单位,向后移动1个单位,如下图所示:
默认的摄像机角度预置有另一个名为“Medium”的子组件,它向上2个单位,向后2个单位,这使得摄像机离角色稍微远一点。
要添加一个指向一个坐着的角色的摄像机角度,您可能会添加另一个子对象,它只向上1个单位,向后2个单位。
如果对话系统在摄像头角度预置中没有找到匹配的子对象,则在场景中寻找一个名为x的GameObject(游戏物体)。如果它找到一个,它就把它当作一个绝对的相机位置。它将摄像机移动到与GameObject(游戏物体)相同的位置并旋转。你可以添加空的GameObjects到场景中,指定绝对的摄像机位置。
Default Camera Angles 默认的相机角度
默认的相机角度预制包含这些角度:
Angle 角 | Description 描述 |
---|---|
Closeup 特写镜头 | Front-on head shot 前面的头 |
Closeup Back 特写镜头back | Back of head 后面的头 |
Closeup Left 特写镜头左 | Left side of head 左面的头 |
Closeup Right 特写镜头右 | Right side of head 右面的头 |
Medium 中间 | Head and torso 头部和躯干 |
Medium Back 中间back | Back of head and torso 头和躯干的后部 |
Medium Left 中间左 | Left side of head and torso 头部和躯干的左侧 |
Medium Right 中间右 | Right side of head and torso 头部和躯干的右侧 |
Full 完整的 | Front-on body 前面的身体 |
Full Back 完整bakc | Back of body 后面的身体 |
Full Left 完整左 | Left side of body 身体左侧 |
Full Right 完整右 | Right side of body 身体右侧 |
Wide 宽 | Body with space (farther than Medium shots) 有空间的身体(比中景更远) |
OTS Left OTS左 | Over the left shoulder 左肩以上 |
OTS Right OTS右 | Over the right shoulder 右肩以上 |
Down 下来 | Looking down on the subject 看下面 |
Up 向上 | Looking up at the subject 抬头看 |
Camera Angle Editor 相机角度的编辑
您可以使用相机角度编辑器工具来帮助您创建相机角度预制组件。使用相机角度编辑器:
- 1.Select menu item Tools → Pixel Crushers → Dialogue System → Tools → Camera Angle Editor.
- 2.主题:在场景中分配一个角色。编辑器将在游戏视图中显示与该角色相关的摄像机角度。
- 3.相机角度收集:分配一个游戏对象。您可以从参考资料中的默认角度预置开始,也可以从头开始创建自己的角度预置。如果你指定一个预制件,你只能编辑现有的角度。要添加新的角度,你必须点击按钮来实例化预制的场景对象。
- 4.相机角度:从下拉菜单中选择相机角度。游戏视图将移动到所选择的摄像机角度的位置。要添加一个新的相机角度,点击弹出菜单旁边的“+”。
记住将你的新相机角度集合保存为一个预制的或者场景对象,这样你就可以将它分配给你的对话管理器的显示设置。
7、任务系统
任务通常是通过与npc对话来开始和完成的。对话系统提供了一个集成的任务系统,使得在对话和游戏过程中管理任务变得很容易。
Writing Quests 写作任务
使用对话编辑器的任务/条目部分来编写任务。
Quest Fields 探索领域任务
Field | Description 描述 |
---|---|
Name 名字 | 对话数据库中任务的名称。如果Use Display Name 使用显示名称 is unticked, this name is also used in UIs. 未勾选此项,此名称也在ui中使用。 |
Use Display Name 使用显示名称 | 在UIs中使用不同于的名称Name 的名字 field. 字段。 |
Display Name 显示名称 | 如果Use Display Name 使用显示名称要在ui中使用的名称。 |
Use Groups 使用组 | 在用户界面中将任务分组。 |
Group 分组 | 如果Use Groups (被勾选)将这个任务分类的组。 |
State 状态 | 任务开始状态。 |
Trackable 可跟踪的 | 任务可以显示在屏幕上的任务跟踪HUD。玩家可以切换跟踪和关闭。 |
Track On Start 在开始跟踪 | W当任务激活时,立即在任务跟踪界面中显示它(跟踪被打开)。 |
Visible 可见 | 可选;如果为真,不要显示在任务日志窗口。 |
Abandonable | 玩家可以放弃任务。 |
Has Entries (Subtasks) 条目(子任务) | 任务有子任务。 |
Description 描述 | 任务的描述,在任务激活时显示在任务日志窗口中。 |
Success Description 成功的描述 | 当任务处于成功状态时显示的描述。如果空白描述显示。 |
Failure Description 故障描述 | 当任务处于失败状态时显示的描述。如果空白,Description 描述 is shown. 显示。 |
Entry # 输入# | (If (如果Has Entries 有项 项目的描述。 |
Entry # State | 输入#状态 条目的起始状态。 |
Markup Tags 标记标签
你可以在任务文本中使用像[var=varName]和[lua(code)]这样的标记。这经常被用在条目中来显示当前的任务计数器的值。
Localization 本地化
你可以在all fields部分或Template选项卡中定义所有文本字段的本地化版本,例如名称、显示名称、描述、条目#等。例如,要添加显示名称的法语版本,请添加字段显示名称fr。
Runtime States 运行时状态
对话编辑器的任务/条目部分显示对话数据库的设计时内容,而不是任务的运行时状态。要在播放期间查看运行时状态,请使用Watches选项卡。
Example Quest 任务演示
这是对话系统演示场景中的一个任务:
- 玩家可以切换任务界面跟踪(Trackable),跟踪开始(Track on Start)。
- 任务完成后会有不同的描述(成功描述)。
- 标记标记以显示当前计数,该计数保存在一个名为enemiesKilled的变量中。
Controlling Quests 控制任务
Controlling Quests in Conversations 在对话中控制任务
您通常可以使用指向并单击Lua向导来检查和设置对话中的任务状态。
Quest-Related Lua Functions Quest-Related Lua函数
如果你想直接使用quest management Lua函数,可以总结如下:
Lua Function Lua函数 | Description 描述 | Example 例子 |
---|---|---|
CurrentQuestState(questName) | Returns a quest state as “unassigned”, “active”, “success”, or “failure” | CurrentQuestState(“Kill 5 Rats”) == “active” |
SetQuestState(questName, state) | Sets a quest state 设置任务状态 | SetQuestState(“Kill 5 Rats”, “success”) |
CurrentQuestEntryState(questName, entryNum) | Returns a quest entry state 返回任务进入状态 | CurrentQuestEntryState(“Escape”, 2) == “active” |
SetQuestEntryState(questName, entryNum, state) | Sets a quest entry state 设置任务进入状态 | SetQuestEntryState(“Escape”, 2, “success”) |
Quest Management Triggers 任务触发管理器
你可以使用这些组件来控制任务:
- Increment On Destroy 在杀死或收集目标时,增加毁灭任务的指示物。
- Dialogue System Trigger 对话系统触发器-通用动作。
- Condition Observer 状态观察器——当条件为真时,监视条件并执行操作。
- Timeline Set Quest State playable时间轴设置任务状态可玩-控制时间轴上的任务。
- The general-purpose Trigger Event, Collision Event, Timed Event components are also useful for managing quests. 通用触发事件、冲突事件、定时事件组件对于管理任务也很有用。
Controlling Quests in Scripts 控制脚本中的任务
QuestLog类提供了添加和删除任务、获取和设置它们的状态以及获取它们的描述的方法。这是一个静态类,因此你可以调用它的方法,而不必创建一个QuestLog对象。
注意,任务状态通常在对话中更新。在大多数情况下,您可能会在对话期间使用指向并单击Lua向导来设置任务状态,因此你可能永远不需要使用这个类中的许多方法。
如果你使用这些方法,你不必将空格和连字符转换为下划线(如关于表索引的重要说明中所述);
QuestLog类将自动为你完成此任务。
Quest State Messages 任务状态信息
当任务状态改变时,对话系统发送一个OnQuestStateChange消息。
Quest Management Example 任务管理的示例
在上面的例子任务中,NPC Sergeant Graves在对话中给玩家一个kill任务:
在突出显示的节点中,使用指向并单击Lua向导设置了脚本字段。它做两件事:
- 设置任务激活。
- 设置警报变量,以便在对话结束时显示警报消息。
每个敌人有一个增量的摧毁组件,增加一个变量命名为敌人被杀。
组件的OnIncrement()事件也运行OnUse方法的对话系统触发器的游戏对象名为敌人:
多人任务
如何在多人游戏中管理任务很大程度上取决于游戏的设计。
在许多情况下,你可以在每个客户端为每个玩家维护对话系统环境(包括任务)。
但是,如果您使用的是权威的主服务器,比如MMO,您可能希望在主服务器上验证任务状态,以防止作弊。为此,将覆盖方法分配给这些委托:
- QuestLog.SetQuestStateOverride
- QuestLog.CurrentQuestStateOverride
在SetQuestStateOverride方法中,联系主服务器以确认允许玩家设置请求的状态。如果是,调用QuestLog.DefaultSetQuestState(),它将在本地设置quest状态,更新跟踪器,并通知侦听器。
在CurrentQuestStateOverride方法中,联系主服务器以确认玩家的权威任务状态。此方法的使用可能比SetQuestStateOverride更复杂。与主服务器的通信通常是异步的;您的override方法可能无法立即返回quest状态,因为它需要等待来自主服务器的响应。相反,您的方法可以返回一个异步操作的字符串引用。然后,调用CurrentQuestState()的代码可以等待异步操作完成并从响应中检索quest状态,而不是立即使用override方法的返回值作为quest状态。
任务状态经常在对话中被检查和设置。当使用不立即返回值的异步重写方法时,您可能希望配置对话条目的序列,以等待表明异步方法已完成的排序器消息。在对话项中,使用WaitForMessage()排序器命令等待排序器消息。在异步方法中,使用sequencer . message()方法来发送排序器消息。如果对话项被配置为等待一个任务状态(即任务状态)。,您已经设置了CurrentQuestStateOverride),您可以注册一个额外的Lua函数,您可以在下一个对话条目中使用该函数来返回从主服务器接收到的值。
如果你的任务使用任务条目(子任务),你也可以设置这些覆盖:
- QuestLog.SetQuestEntryStateOverride
- QuestLog.CurrentQuestEntryStateOverride
任务界面
Quest Log Window 任务日志窗口
任务日志窗口显示了玩家的活动任务和完成任务的详细信息。设置任务日志窗口的推荐方法是使用标准的UI任务日志窗口组件。
** 标准的UI任务日志窗口**
标准的UI任务日志窗口管理上面屏幕截图中显示的UI元素。这些元素是:
- 主面板:控制在显示活动任务和完成任务之间的切换。
- 选择面板:显示任务标题,可选的包含在组文件夹中。玩家可以切换跟踪或者选择一个任务来查看它的细节。
- 细节面板:显示当前选择的任务的细节。
所有的UI元素都可以重新定位和调整。
设置任务日志窗口最简单的方法是使用Prefabs ► Standard UI Prefabs ► Basic这个预制组件被分配给对话管理器预制组件的实例化预制组件,这意味着它将在对话管理器的画布下自动实例化。
标准的用户界面任务日志窗口组件有以下属性:
HUD任务系统
任务指标
你可以使用任务指示来告诉玩家NPC有任务信息。
设置任务指示:
- 添加指示游戏对象到NPC。例如,添加一个带有一个或多个图像的Unity UI world space canvas,例如一个问号表示有新的任务可用,一个感叹号表示NPC有任务更新。在DemoScene2场景中,NPC中士Graves有一个任务指示画布。
- 添加一个Quest State Indicator 任务状态指示器给NPC这允许您将gameobject(游戏物体)(如world space canvas图像)与数字指示符级别相关联。关于格雷夫斯中士,指标是:
Level 0: nothing 0级:没有
Level 1: question mark 第一级:问号
Level 2: exclamation mark 二级:感叹号 - 向NPC添加一个任务状态监听组件。当任务状态发生变化时,该组件会更新任务状态指示器的当前指示器级别,并通过UnityEvent(可以在检查器中连接)可选地做其他事情。若要配置任务状态监听器,请将元素添加到任务状态指示器级别折叠中。在每个元素中,指定一个任务状态和与任务状态相关联的指示符级别。任务进入状态也有相应的折页。最高指示级别总是优先级。如果你的NPC涉及多个任务,你可以添加多个任务状态监听器。
8、保存系统
对话系统采用Pixel Crushers Common Library’s的保存系统。
在演示场景中配置了Save系统组件。对话管理器有一个保存系统组件和一些与保存系统组件相关的组件:
演示菜单调用静态脚本方法SaveSystem.SaveToSlot()来保存游戏,调用SaveSystem.LoadFromSlot()来加载游戏。
保存系统设置
- 1.在场景中添加一个保存系统组件——例如在演示场景中的对话管理器上。Save System组件将使GameObject作为一个持久的单例对象,这意味着它在场景更改后仍然存在,并且通常只有一个实例。
- 2.添加对话系统保护程序。此组件将对话系统的数据发送到保存系统。
- 3.添加一个Json数据序列化器组件。该组件将二进制保存的游戏数据转换为可保存的格式—在本例中是JSON文本。如果您想要使用不同的序列化器,您可以添加您自己的DataSerializer类的实现。
- 4.添加一个Player Prefs保存的游戏数据存储器或磁盘保存的游戏存储器组件。此组件将序列化的数据写入持久存储(如PlayerPrefs或加密的本地磁盘文件)。所有平台都支持Player Prefs保存的游戏数据存储。在独立的构建中支持磁盘保存的游戏存储程序。如果您想以不同的方式存储游戏,您可以添加自己的SavedGameDataStorer类的实现。
- 5.可选地添加一个标准的场景转换管理器。该组件可以在改变场景时加载中间加载屏幕场景和/或播放淡入淡出等动画。在演示场景中,转换管理器被配置为在场景更改期间淡入黑色。更多信息,请参见场景转换管理器。
保存组件设置
添加这些组件到任何游戏对象的状态,你想要保存:
Component 组件 | Function 函数 |
---|---|
Active Saver | 保存游戏对象的活动/非活动状态。如果GameObject开始不活动,将此组件添加到保证为活动的不同GameObject中,并分配目标GameObject。 |
Multi Active Saver r | 保存多个游戏对象的活动/非活动状态。 |
Animator Saverr | 保存GameObject 's animator的状态。 |
Destructible Saver r | 保存时,游戏对象已被销毁或禁用。下一次加载游戏或场景时,如果GameObject之前已经被销毁/禁用,这个脚本将再次销毁/停用它。如果指定了预制件,它还会产生一个被破坏的替换版本。 |
Enabled Saver r | 保存组件的启用/禁用状态。如果GameObject启动为非活动状态,则将此组件添加到保证为活动的不同GameObject中,并分配目标组件。 |
Position Saver r | 保存游戏对象的位置和旋转。 |
保存和加载
要从脚本中保存和加载游戏,请使用静态方法pixelcrusher . savesystem。SaveGameToSlot PixelCrushers.SaveSystem.LoadGameFromSlot。
保存系统的方法
要在不使用脚本的情况下访问Save系统方法,例如在一个UI按钮的OnClick()事件中,添加一个Save系统方法组件,并配置UI按钮来调用组件的SaveSlot和LoadFromSlot方法。
检查点保存
关卡保存是当玩家进入时自动保存游戏的触发区域。设置一个检查点保存:
- 1.创建一个游戏对象,并添加一个触发器碰撞器。(至少有一个对象,即玩家或触发器,可能需要一个刚体来记录触发冲突。)
- 2.添加保存系统方法组件。
- 3.添加一个Trigger Event 触发事件 组件
– 将标签蒙版设置为适当的蒙版,例如Player。
– 配置On Trigger Enter事件来调用SaveSystemMethods。保存你想要使用的游戏插槽号。
– 你可能还想在触发器中禁用GameObject(游戏物体),这样它就不会重新触发。
自动保存和加载
手机游戏通常在玩家关闭游戏时自动保存,在玩家重新开始游戏时自动加载。要将此行为添加到您的游戏,添加一个自动保存加载组件到保存系统: - 1.启动时勾选加载,启动时加载保存的游戏(如果存在),退出时勾选保存,退出时保存游戏。
- 2.当玩家暂停/最小化游戏时,勾选Save On Pause来保存游戏。这样,如果玩家暂停应用程序并杀死它,游戏将被正确保存,而不是在应用程序本身中正常退出。
- 3.当应用程序失去焦点时,勾选Save On Lose Focus来保存游戏。
改变场景
使用LoadLevel()序列器命令
要使用对话系统感知更改场景,请使用LoadLevel()排序器命令。
或者,在c#中使用SaveSystem.LoadScene(),或者将UnityEvents连接到SaveSystemMethods.LoadScene。
场景过渡管理
要播放动画,并/或显示加载场景,而加载下一个实际的场景,添加一个标准的场景转换管理器到您的保存系统:
如果有场景转换管理器,保存系统将:
- 1.设置离开场景转换的动画器触发器(如果指定)。
- 2.加载加载场景(如果指定)。
- 3.异步加载下一个实际场景。
- 4.在实际场景加载后,设置进入场景转换的触发器(如果指定)。
生成对象
对话系统有一个生成的对象管理器,它可以跟踪在运行时实例化到场景中的对象,并将它们包含在已保存的游戏中。当你加载一个游戏时,它会重新实例化对象。
这是配置过程的概述:
- 1.将生成的对象组件添加到对象预置中。
- 2.将生成的对象管理器添加到场景中,并将对象预置分配给它。
创建生成对象预制
将派生的对象组件添加到将被实例化的预制组件中。重复所有可以在你想要保存的游戏场景中实例化的项目。
创建衍生对象管理器
创建一个空的GameObject并添加一个衍生对象管理器组件,如下所示。每个场景都应该有自己的派生对象管理器。
将场景中可以创建的所有衍生对象预制块添加到衍生对象预制块列表中。如果列表中缺少预制组件,那么在加载游戏或返回场景时,派生的对象管理器将无法重新派生它。在上面的示例屏幕快照中,一个名为“pickup_sniper_”的预制组件被添加到列表中。
保存系统概述流程图
下图概述了保存系统与对话系统的工作原理:
加载的过程是自下往上的。
当改变场景时,除了不使用保存的游戏数据存储器外,整个过程是一样的。保存系统只是将保存的数据保存在内存中,并将其应用到新加载的场景中。保存系统在改变场景时执行以下步骤:
- 1.告诉当前场景中的所有保护程序组件保存它们的状态。
- 2.告诉所有的保护程序组件,他们将被卸载,所以如果他们更新一个计数器销毁时,他们应该忽略它这一次。
- 3.如果有场景转换管理器,则播放“离开当前场景”转换(例如,淡出或加载加载屏幕场景)。
- 4.加载下一个场景异步。
- 5.如果有场景转换管理器,则播放“进入新场景”转换(例如,淡入)。
- 6.告诉新场景中的所有保护程序组件从保存的数据更新它们的状态。
9、本地化
对话系统支持对话数据库的语言本地化,并提供通用文本表。
当您从默认设置更改语言时,对话系统将使用包含指定语言本地化版本的字段中的文本。
对话系统支持Inter-Illusion的I2定位。如果您使用I2本地化,您可能想要使用对话系统的I2本地化支持支持。
语言代码
于每种本地化语言,您都将使用一种语言代码。代码由您决定,但是一个好的选择是ISO 639-1标准:https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes。
Example language codes are: 示例语言代码如下:
Code 代码 | Language 语言 |
---|---|
es | Spanish 西班牙语 |
ru | Russian 俄罗斯 |
fr-CA | French (Canadian) 法语(加拿大) |
可本地化的对话数据库字段
通过在字段名中添加空格和语言代码,所有字段都是可本地化的。唯一的例外是对话文本字段。对于对话文本,单独使用语言代码。将本地化字段的类型设置为本地化。
下面的字段是要本地化的常见字段。如果没有为当前语言定义本地化字段名,它将使用默认字段。
常见本地化的对话输入字段
对于每种语言LN,对话输入字段的名称为:
Default Field | Localized Field | Example |
---|---|---|
Dialogue Text | LN | es |
Menu Text | Menu Text LN | Menu Text es |
Sequence | Sequence LN | Sequence es |
Response Menu Sequence | Response Menu Sequence LN | Response Menu Sequence es |
探索领域
对于每种语言LN,任务域的名字是:
Default Field | Localized Field | Example |
---|---|---|
Name | Name LN | Name es |
Description | Description LN | Description es |
Success Description | Success Description LN | Success Description es |
Failure Description | Failure Description LN | Failure Description es |
Entry # | Entry # LN | Entry 3 es |
在Lua代码中,可以使用GetLocalizedText()函数来获取字段的本地化版本,这在对话输入脚本或条件字段或使用[Lua (code)]标记标记时非常有用。
如何在对话编辑器中本地化
使用对话编辑器进行本地化的最简单方法是向template选项卡上的模板添加本地化字段。这样,当您添加它们时,它们将自动添加到资产中。
按照下面的说明将本地化添加到对话数据库中。
如何本地化对话
这些步骤演示了如何将西班牙语(es)和俄语(ru)添加到对话中。
-
1.在“模板”选项卡上展开Dialogue Entries 对话记录 foldout. 折页。
单击与对话条目标题相同的行上的+以添加字段。
在标题中,输入语言代码。
设置Type 类型Localization
选择 Menu → Apply Template to Assets,将更改应用于所有现有的对话项。 -
在Conversations选项卡上,检查对话条目节点。
将翻译添加到本地化字段:
如何本地化任务
这些步骤演示了如何将西班牙语(es)和俄语(ru)添加到任务中。 -
1.在“模板”选项卡上展开Quests 任务 foldout. 折页。
在任务标题的同一行点击+来添加一个字段。
在Title 标题后跟空格和语言代码。
设置Type 类型 为Localization -
在任务选项卡上,检查一个任务。
把你的翻译添加到任务中:
对话编辑器本地化导出/导入折叠
导入格式的本地化
10、脚本编写
源代码的概述
Namespaces 名称空间
所有对话系统源代码都包含在名称空间 PixelCrushers.DialogueSystem.
namespace. PixelCrushers公共库源代码在PixelCrushers名称空间中。
Language.Lua包含在名称空间中。
代码概述
: 对话系统采用模型-视图-控制器(MVC)架构:
MVC | Description 描述 |
---|---|
Model 模型 | 对话数据库、Lua和活动对话的状态。 |
View 视图 | 对话UI和过场音序器。 |
Controller 控制器 | 在模型和视图之间进行中介。 |
常用的方法
DialogueManager Class
PixelCrushers.DialogueSystem.DialogueManager.Bark:
DialogueManager.Bark("Converation With Bark Lines", barker.transform);
PixelCrushers.DialogueSystem.DialogueManager.BarkString:
DialogueManager.BarkString("I'm barking this text.", barker.transform);
PixelCrushers.DialogueSystem.DialogueManager.GetLocalizedText:
DialogueManager.SetLanguage("fr");string frenchForCheese = DialogueManager.GetLocalizedText("cheese");
PixelCrushers.DialogueSystem.DialogueManager.PlaySequence:
DialogueManager.PlaySequence("Fade(in,2); Audio(Tada)@2");
PixelCrushers.DialogueSystem.DialogueManager.SendUpdateTracker:
DialogueManager.SendUpdateTracker(); // Manually refresh quest tracker HUD & quest log window displays.
PixelCrushers.DialogueSystem.DialogueManager.ShowAlert:
DialogueManager.ShowAlert("This is an alert.");
PixelCrushers.DialogueSystem.DialogueManager.StartConversation:
DialogueManager.StartConversation("Some Conversation", actor.transform, conversant.transform);
PixelCrushers.DialogueSystem.DialogueManager.StopConversation:
DialogueManager.StopConversation();
DialogueLua Class
PixelCrushers.DialogueSystem.DialogueLua.GetVariable:
string s = DialogueLua.GetVariable("favoriteColor").asString;
PixelCrushers.DialogueSystem.DialogueLua.SetVariable:
DialogueLua.SetVariable("favoriteColor", "blue");
QuestLog Class
PixelCrushers.DialogueSystem.QuestLog.GetQuestState:
QuestState state = QuestLog.GetQuestState("The Holy Grail");
PixelCrushers.DialogueSystem.QuestLog.SetQuestState:
QuestLog.SetQuestState("The Holy Grail", QuestState.Active);
PixelCrushers.DialogueSystem.QuestLog.GetAllQuests:
string[] quests = QuestLog.GetAllQuests()
SaveSystem Class
PixelCrushers.SaveSystem.SaveToSlot:
SaveSystem.SaveToSlot(1);
PixelCrushers.SaveSystem.LoadFromSlot:
SaveSystem.LoadFromSlot(1);
PixelCrushers.SaveSystem.LoadScene:
SaveSystem.LoadScene("Tavern@Entryway"); // Load Tavern scene, move player to position of Entryway GameObject.
对话系统Attributes
ConversationPopup Attribute ConversationPopup属性
使用[ConversationPopup]属性将字符串转换为conversation popup。它有一个可选的bool参数来显示数据库选择字段。
using UnityEngine;
using PixelCrushers.DialogueSystem;
public class MyClass : MonoBehaviour
{
[ConversationPopup]
public string conversation; // Shown without database selection field.
[ConversationPopup(true)]
public string conversation2; // Shown WITH database selection field.
}
QuestPopup Attribute QuestPopup属性
在你的类定义中使用[QuestPopup]属性将一个字符串转换成一个quest popup。它有一个可选的bool参数来显示数据库选择字段。
using UnityEngine;
using PixelCrushers.DialogueSystem;
public class MyClass : MonoBehaviour
{
[QuestPopup]
public string questName; // Shown without database selection field.
[QuestPopup(true)]
public string questName2; // Shown WITH a database selection field.
}
QuestEntryPopup Attribute QuestEntryPopup属性
在你的类定义中使用[QuestEntryPopup]属性将一个int类型转换成一个任务条目弹出。注意:只有当您的脚本中有一个名为’quest’、‘questTitle’、‘questName’、‘quest’、'questTitle’或’questName’的字符串变量时,这个属性才会起作用。这就是任务条目弹出窗口知道显示哪个任务条目的方式。
using UnityEngine;
using PixelCrushers.DialogueSystem;
public class MyClass : MonoBehaviour
{
[QuestPopup]
public string questName;
[QuestEntryPopup)]
public string questName2; // Shows a popup with the entries defined in the quest named by questName.
}
11、导入&导出
对话系统可以导入和导出几种格式:
导入格式
- articy:draft
- Aurora Toolset
- Chat Mapper
- CSV
- Ink
- TalkIt
- Twine
- Importing Your Own Formats
导出格式
- 导出XML到聊天映射器
- 导出到逗号分隔值(CSV)
- 导出画外音脚本
- 导出语言文本Text
导入自己的格式
. 要导入不同的格式,请复制Templates►Scripts►ConverterWindowTemplate.cs
导出其他的格式
对话编辑器的数据库选项卡有一个导出文件夹,允许您以这些格式导出对话数据库数据:
- XML
- CSV
- Voiceover Script
- Text
12、组件参考
Always Face Camera
Component > Pixel Crushers > Dialogue System > Actor > Always Face Camera
始终面对摄像机使游戏对象始终面对主摄像机。
属性
属性 | 功能 |
---|---|
YAxis | 只能在y轴上转动。 |
Rotate 180 | 如果对象是面向后的,则勾选。 |
Bark Group Member
Component > Pixel Crushers > Dialogue System > Actor > Bark Group Member
对话组成员将GameObject配置为对话组的成员。当一个组的一个成员对话,其他成员将隐藏任何活动的对话
属性
属性 | 功能 |
---|---|
Group Id | 指定组的字符串或Lua表达式 |
Evaluate Id Every Bark | 勾选以重新评估成员ID。 |
Forced Hide Delay | 当隐藏一个活动的对话,等待的时间量之前,实际上隐藏它。 |
Bark On Idle
Component > Pixel Crushers > Dialogue System > Trigger > Bark On Idle
在空闲时对话,每隔一段时间就自动对话一次。
Cinemachine Priority On Dialogue Event
Component > Pixel Crushers > Dialogue System > Trigger > On Dialogue Event > Cinemachine Priority On Dialogue Event
当对话事件发生时,设置Cinemachine虚拟摄像机的优先级。
Condition Observer
Component > Pixel Crushers > Dialogue System > Trigger > Condition Observer
条件观察器以常规频率检查条件,并在条件为真时运行操作。
Conversation Logger
Component > Pixel Crushers > Dialogue System > Misc > Conversation Logger
将对话活动记录到控制台。
Default Camera Angle
Component > Pixel Crushers > Dialogue System > Actor > Default Camera Angle
设置演员的默认摄像机角度。
Dialogue Actor
Component > Pixel Crushers > Dialogue System > Actor > Dialogue Actor
可选组件,允许您将GameObject与actor相关联,并配置它在UIs中的显示方式。
Dialogue System Events
Component > Pixel Crushers > Dialogue System > Miscellaneous > Dialogue System Events
将对话系统事件统一显示。
Dialogue System Controller
Component > Pixel Crushers > Dialogue System > Misc > Dialogue System Controller
这是主要的对话系统组件,在对话管理器一节中有详细的描述。
Dialogue System Trigger
Component > Pixel Crushers Dialogue System > Trigger > Dialogue System Trigger
当触发事件发生时,对话系统触发器组件可以执行许多对话系统操作。
Extra Databases
Component > Pixel Crushers > Dialogue System > Misc > Extra Databases
在运行时环境中添加和删除额外的数据库。
Increment On Destroy
Component > Pixel Crushers > Dialogue System > Actor > Increment On Destroy
当游戏对象被销毁或禁用时,Lua变量的销毁增量。
Lua Console
Lua控制台提供了一个游戏内接口,您可以在其中运行Lua命令。
Override Dialogue UI
Component > Pixel Crushers > Dialogue System > UI > Override > Override Dialogue UI
覆盖对话管理器的对话UI,用于涉及GameObject(游戏对象)的对话。
Override Display Settings
Component > Pixel Crushers > Dialogue System > UI > Override > Override Display Settings
覆盖对话管理器对涉及此游戏对象的对话的显示设置。
Proximity Selector
Component > Pixel Crushers > Dialogue System > Actor > Player > Proximity Selector
接近选择器为玩家提供了一个界面来瞄准“usables”并通过输入他们的触发区域向他们发送“OnUse”消息。
Range Trigger
Component > Pixel Crushers > Dialogue System > Actor > Range Trigger
距离触发只在玩家处于触发区域时激活游戏对象和/或组件。
Selector
Component > Pixel Crushers > Dialogue System > Actor > Player > Selector
选择器为玩家提供了一个接口来定位可用的组件并向它们发送OnUse消息。
Selector Use Standard UI Elements
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Selection > Selector Use Standard UI Elements
修改选择器或接近选择器以使用标准的UI选择器元素。
Sequencer Shortcuts
Component > Pixel Crushers > Dialogue System > Misc > Sequencer Shortcuts
为排序器命令定义别名。
Standard Bark UI
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Bark > Standard Bark UI
使用对话系统的标准UI系统显示对话。
Standard Dialogue UI
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Dialogue > Standard Dialogue UI
使用对话系统的标准UI系统管理对话UI。
Standard UI Menu Panel
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Dialogue > Standard UI Menu Panel
放置在将由标准对话UI使用的菜单面板上。
Standard UI Quest Log Window
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Quest > Standard UI Quest Log Window
使用对话系统的标准UI系统管理一个任务日志窗口。
Standard UI Quest Tracker
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Quest > Standard UI Quest Tracker
使用对话系统的标准UI系统管理一个任务跟踪界面。
Standard UI Subtitle Panel
Component > Pixel Crushers > Dialogue System > UI > Standard UI > Dialogue > Standard UI Subtitle Panel
放置在将被标准对话UI使用的字幕面板上。
Timeline Trigger
Component > Pixel Crushers > Dialogue System > Trigger > Timeline Trigger
当指定事件发生时触发时间线(可播放的控制器)。
Usable
Component > Pixel Crushers > Dialogue System > Actor > Usable
指定GameObject(游戏对象)是可用的——也就是说,玩家可以瞄准它并发送OnUse消息。
四、案例演示
案例一、简单对话
步骤:
1.步骤1.创建一个新场景(File → New Scene).
步骤2.拖动预制体 Dialogue Manager进入场景:
步骤3.建立一个对话数据库,单击Create:
步骤4.在为数据库指定好路径以及名字之后,再次打开“对话编辑器”窗口:
步骤5.单击Conversations标签,单击“+”按钮添加新会话。
步骤6.新建两个对话节点
步骤7.在节点的Inspector面板,分别设置Dialogue Text为“Hello.”,“Goodbye.”
步骤8.创建一个空游戏对象重命名为“Player”,创建一个Cube命名为NPC将空游戏对象。
步骤9,点击NPC。加一个对话系统触发器:
步骤10.单击Add Action并选择Start Conversation:
步骤11.从Conversation下拉,指定Conversation字段为New Conversation 1,并将Player分配给Conversation Actor,NPC分配给Conversation Conversant.
步骤12.最后,设置Trigger为On Start。这告诉对话系统触发器在场景开始时执行其操作。
第13步,现在开始你的第一次对话。
步骤14.现在加入交互。点击NPC,找到Dialogue System Trigger组件。设置Trigger为On Use。对话系统触发器在接收OnUse消息时执行其操作
步骤15.为NPC添加Usable组件。这是交互组件,说明NPC可被点击的最大距离是30
步骤16.点击Player对象并添加一个Selector组件。设置Select At为Mouse Position:
步骤17.现在再启动场景。将鼠标放置在立方体上,以便看到以下黄色消息:
这意味着玩家的选择器组件已经检测到NPC的可用组件。现在按空格键或鼠标右键。
Selector组件将向NPC发送OnUse消息,NPC的对话系统触发器将通过启动会话来响应。
步骤18.控制Selector组件在会话期间保持活动状态,添加一个Dialogue System Events组件:
案例二、《功夫》中经典对话
步骤1.创建对话数据库,输入台词
步骤2.在项目中找到Dialogue Manager、Player、Private Hart、Room预制体,拖入到场景中:
步骤3.指定对话数据库到你新建的数据库
Player:
Private Hart:
步骤4.更改Dialogue System的对话皮肤:
直接找到这个预制体拖入卡槽中就行:
Basic Standard UI Selector Elements.prefab
步骤5.运行一下试试吧
源工程下载:
https://github.com/764424567/Demo_DialogueSystem