Godot4:如何快速上手并玩转免费对话系统插件Dialogue Manager

引言

大家好,我是灰(微博红薯@天外灰仙儿,优快云@overpara灰),照例寒暄几句~

今天给大家带来一个使用Godot存在很久的对话插件的教程,名为Dialogue Manager,作者是Nathan Hoad,作者本人也在油管上发布了教程视频,但是是英文版的,并且仅仅展示了一部分功能。那么现在让我来带着大家去全面学习一下这款非常好用的对话插件(教程内容基础部分也是基于作者的视频教程)!当然如果想完全掌握这个插件,还需要去Github上查看文档并阅读源码,本文只列举了常用功能。

本篇不是完全零基础的教程,但是只要你用过一点儿Godot就都可以看懂!如果看起来比较吃力,可以到我主页找一找Godot入门教程或者直接从桌宠教程开始学起!

在正式开始前可以给大家看看效果(UI风格使用的是默认的,在原有的基础上增加了头像功能):

一、准备工作

在跟着教程做之前,还需要准备一下素材(非常感谢我们辉鸦工作室老板做的素材,是迷宫饭的同人图嘿嘿):

1. 人物头像or立绘

在这里我准备了四张头像,分别对应了两个角色每人两张,你可以准备的更少一些或者直接使用Godot自带的那个icon.svg,或者随便在网上找找嘛!不想用头像也可以直接使用立绘,毕竟也有很多游戏是在对话时直接展示立绘的(比如大部分手游),原理是一样的,这里我就用头像了!不管你用头像还是立绘,确保每张图的尺寸是相同的!

2. 角色在游戏内的图

我这里也是准备了两个角色,当然你也可以一个角色自言自语,当然当然你也可以直接用icon.svg,仅仅学习一下功能!

3. 非必要素材

按键提醒贴图(我直接用的文字),以及角色说话时的音效(像sans那样嘚嘚嘚的)、一个背景图片(显得不是那么怪)、一个用于交互的物体(在这里我模仿原作者的演示视频用了苹果树)。

4. 创建一个本次课程用的工程

在这里我用的是Godot4.3,你使用任何主流版本应该都可以(包括3.5),我就起名叫DialogLearningv1了,万一以后有v2呢是吧:

这里我手快了不小心先创建了再截的图……所以说我不是空文件夹。

5. 下载插件

俗话说万事开头难,这难就难在了Godot的服务器不在国内,所以大家需要用特殊手段获取一下。要么大家在引擎内部的AssetLib直接搜索Dialogue Manager直接下载并安装:

要么大家可以去Godot的官网,找到Assets:

在这里搜索Dialogue Manager,你是4.1+的版本就点上面那个,是3.5的版本就点下面那个:

这里我因为用的是4.3版本,所以点上面那个,点进去之后选择Download下载:

如果官网都打不开,那你直接来找我要或者到群文件下载!

6. 安装插件

如果是从引擎中直接下载的插件是可以直接安装的,但是如果你是从外部下载的插件那你应该会获得一个压缩包,解压之后找到里面的addons文件夹:

把这个文件夹整个复制到你的游戏工程根目录下,如图所示就是对嘞:

在菜单栏打开项目设置:

在“插件”这一栏勾选上“启用”:

引擎上方多出来个这个就算成功:

二、创建对话文本

接下来我来带着大家写一些对话,我们首先在文件系统里建一个文件夹,专门用来存放对话的文本,养成文件分类的好习惯哈,这里我起名叫“DialogText”:

然后我们选择Dialogue视图,点击左上角的新建:

大家路径就选择刚刚建立的文件夹,起一个文件名,在这里我就叫“MyDialog”,然后点确定:

这里大家可以看到,插件已经为我们自动生成了一段示例,目前看起来还太过复杂,我们可以都删掉,我来带大家一点点由浅入深地写~

1. Hello World

首先大家可以打最简单的一句话,Hello World!

然后大家可以点击这个播放按钮,进行预览:

可以看到可直接正常显示(按空格或者鼠标左键继续):

2. 角色名

那我们做对话的话,应该不会只有旁白(除非你做史丹利的寓言),那这个时候我们就需要添加角色的名字:

也就是角色名后面跟着冒号,冒号后面跟着空格冒号一定要是英文的冒号!当输入正确时,角色名会变成蓝色。在这里给大家举几个错误案例:

运行后,可以看到角色名已经和正文不是一个字体了:

3. 选项

如果你想做以对话为核心的游戏,那么选项必不可少,我们来看一下选项如何实现:

可以看到,一个小横杠-  跟着一个空格,再后面的一句话就是选项了,大家可以运行一下看看实际效果(同样的,如果格式正确小横杠会变成蓝色),大家可以用小键盘或者鼠标直接切换选项:

不过因为我们没有在后面设置对话,所以选择完后游戏会直接结束,那我们为了体现出选项的差异性,可以在后面再添加一些对话:

如果想在选项后面增加分支的话,那就在下面一行按Tab键缩进一下,再写入该选项对应的后续对话。也可以在整个选项都结束后,写入通用的后续对话。大家可以在这块多试一试!

4. Title

如果你的剧情自由度很高的话,那么不同的选项分支往往会导致完全不同的剧情,此时再把分支剧情都塞到选项下面的缩进里未免显得太过繁琐了。

我们采取Title的方式来解决这个问题,大家请看,这里我列举作者本人在示例视频中的例子:

相信聪明的大家也可以看出来,=>这个等于号和一个大于号,加一起就像一个箭头一样,指向后面的Title(也就是标题),然后会直接跳转到~波浪线开头的对应标题!

那么很简单,波浪线加空格后面跟着的就是Title,而=>可以跳转到对应的标题。大家如果书写格式正确的话,会显示为紫色的字。

大家也可以在左下角这个地方看到每个标题的名字:

那么大家运行之后会发现一个问题,那就是对话直接从apple_gave开始播放了,这是因为这个插件默认会从第一个标题开始播放,所以我们需要给整个对话开头再加一个标题,一般来说会用start:

当然,如果你的对话文本体量非常大的话,还可以在这里点击任意一个Title,这个时候就会从对应的Title开始运行,非常方便:

大家还会发现一个问题,就是apple_gave这段的对话结束后,会继续播放goodbye这段的对话,这肯定不是我们希望看见的。如果我们想在某个位置直接结束掉对话,可以使用=> END:

这样播放起来就没有问题了!同时大家如果希望播放完Title中的内容还可以返回到当前行,可以使用=><符号跟着空格和Title。

5. 注释

当你的游戏开发周期很长的时候,不仅代码中需要加注释,对话文本中同样需要注释,添加方法如下:

与在代码中打注释的方法相同,区别在于在对话文本中注释必须自己单独一行,不可以和其他内容写到同一行~

6. Tag

有的时候我们需要给台词挂上Tag(标签),比如标注上角色的情绪、表情等信息,如图:

其实跟注释很像,不过外部多了一个英文方括号[],在这里happy就是这句台词的tag了。一般推荐把tag写到台词的开头,也就是我写的这个位置

当然只有一个值不太好调用,我们也可以弄成类似字典的键值对形式:

比如这里我希望能后面换头像时能用到这个标签,我就把标签名设置为portrait(头像),值设置为mlxe_happy(玛露希尔开心)。

在tag内,不要键入空格,除非有多个tag都需要声明,两个tag之间的逗号后面要跟空格:

7. 读写游戏参数

在对话时,不可避免出现条件判断,比如我这里要给苹果的话,必须要确保手里真的有一个苹果。在这里我们先在文件系统中新建一个存放脚本的文件夹(我就叫src了):

起个名字,就叫GameManager(可以起的跟我不一样,但是后面抄代码的时候也要全都跟着替换,答应我不要有的地方抄有的地方不抄好吗)

我们这个脚本主要是用来存储游戏运行中的各种参数的,比如:

在这里我声明了两个变量,第一个是玩家此时有多少个苹果,第二个则是玩家有没有送过苹果。

我们需要将这样记录游戏全局变量的脚本,放入到AutoLoad中,首先打开项目设置:

在项目设置中选择全局、自动加载、路径:

选择我们刚才创建的脚本,然后点击添加:

注意这个全局变量要勾选上:

在对话中,我们可以直接用if来判断GameManager中的变量,判断完毕后执行的内容需要整体按Tab缩进一下。由于我们条件如果判断失败的话(就是检测到没有苹果),会继续往下执行对话,但是下面的对话就是下一个Title的内容了,所以我们加一个=> END直接结束掉对话。

当然也可以用and和or进行与或的判断,比如我这里加了一个判断,不仅要有苹果,还要送过苹果:

注意在对话文本中写代码是没有代码补全的,所以一定要非常仔细地写,变量名太长的话大家可以直接去代码中复制粘贴~

当苹果给出去后,苹果的数量肯定要减少了,同时要对送出苹果的flag赋true:

可以看到,只要写一个do加空格,后面跟着要执行的代码就可以了。

大家在运行对话时,可以观察一下场景-远程、GameManager的检查器里值的变化:

除此之外,大家还会遇到对话正文里出现变量的情况,比如玩家可以自定义角色的名字,再比如我们这里还可以显示玩家身上的苹果数量:

这里大家用两个花括号{{}}把变量名框起来就可以了!

此时大家可能会觉得,如果有好几个苹果,说“分你一个”还好,但是如果手里只有一个苹果,那就不能算是“分”一个了。那我们就可以用一个简单的条件判断语句:

这里就不详细说格式了,其实也很好理解,先是判断有几个苹果,然后根据苹果数量是否为1来决定用哪一个台词。

此外,如果大家觉得每次打变量名都要加上脚本名太长了,可以用这种方法简写:

先点击上方的设置:

可以在Runtime中,把脚本勾上,勾上后就不用写脚本名了,直接写变量名就可以。但是不是很推荐这种做法

8. 执行方法函数

在对话中执行方法函数的方法和之前给变量赋值的操作一样,也是在前面加一个do和空格,可以方便让角色进行一些动画或者发出信号。如果这个方法不在AutoLoad脚本中的话(比如挂到了角色脚本上),那需要你的对话正在执行的主场景的脚本中,有声明过需要执行方法的节点。这里不好理解的话,我们在后面第七章的部分会进行详细的讲解~

9. 随机对话

为了增加游戏的代入感,随机对话也非常常见,有以下几种随机显示对话的方式:

第一种比较简单,适用于一句话中进行几个简单的随机:

也就是用两个方括号[[]]框起来,中间随机的台词用竖线|隔开。

第二种丰富度更高一些,用百分号%开头,就是随机这几个对话,百分号后面的数字代表着随机权重,2就是概率为没有数字的两倍概率:

第三种更为自由,可以在百分号后面跟着=>来跳转到其他Title,这里就不展示了~

三、对插件进行二创

1. 皮肤(主题)修改

如果你想做风格化独立游戏,那么肯定不会满足于默认的UI显示。下面我来教大家如何自定义你的对话框(也就是气泡),首先在项目根目录里创建个文件夹,用于存放我们自定义的气泡:

然后跟着我选择这一项,中文意思就是创建一个示例对话气泡的复制品:

找到我们刚刚创建的文件夹:

可以看到这个文件夹里多出来了一个场景和一个脚本,大家也可以对这两个文件进行改名以方便之后做更多的对话气泡,注意要改就一起改

我们双击tscn文件进入场景,然后点击2D切换到2D视图:

大家点击Balloon,再选择检查器里的Theme,就可以对该主题文件进行修改颜色、替换贴图了。因为本期不是Theme修改教程,所以详细的大家请自行寻找做UI的教程:

我这里就仅仅对其加上头像了,立绘的添加方法比这个简单,大家可以自己研究一下,其实就是随便摆摆:

大家新建几个文件夹,用于存放头像或者立绘(portraits)、背景(background)、场景中的角色(characters)、互动用的物体(items)以及音效(sfx),当然没有也能做,就用下面那个自带的icon.svg,复制几个改个颜色改个文件名就可以了:

然后大家选择Dialogue节点,右键选择添加子节点:

找到HBoxContainer,然后创建:

拖拽一下,让VBox成为HBox的子节点:

然后选择VBoxContainer,把水平对齐中的扩展打开:

在HBoxContainer中新建一个TextureRect节点用于存放头像,并且保证它在节点树中处于VBox的上方,这样在游戏中头像就会在文字的左边(我这里省略了创建和拖动节点,你可以吗?你可以!):

给TextureRect节点改个名字,就叫Portrait:

把准备好的任意一个头像拖拽到Portrait节点的Texture里:

我们将模式修改成Fit Width Proportional(对齐宽度并保持比例)和Keep Aspect Center(保持比例居中):

如果你的图太小了,可以修改这里的最小宽高:

选择HboxContainer,还可以在Theme Overrides里设置头像和文字的间距(separation):

可以将头像多替换替换成其他的图试试有没有问题:

此外,这里我强烈建议取消勾选DialogueLabel的Fit Content选项,它会导致台词所在的UI区域自由变形造成显示错误:

2. 参数修改

大家选择DialogueLabel节点,可以看到有很多参数可供修改:

这里也给大家依次翻译一下:

Skip Action:跳过对话的快捷键,这里是和输入映射里的快捷键名对应的。注意是跳过当前句的动画,也就是不让它一个字一个字蹦,直接全部出来的快捷键。

seconds_per_step:每个字蹦出来的时间,单位是秒。

pause_at_characters:遇到什么会停顿一下,一般就是句号感叹号问号,注意这里默认的都是英文符号,我们要加上中文的符号。

skip_pause_at_character_if_followed_by:需要停顿的符号后面跟着什么就不需要停顿了,这里默认的右括号和右双引号,比如句号后面是双引号的话就不停顿了。这里默认值也都是英文的,需要大家自己加上中文。

skip_pause_at_abbreviations:如果需要停顿的符号前面是这些缩写也不需要停顿,大家可以展开一下看看:

比如Mr.这个句号就不要停顿了。

seconds_per_pause_step:停顿的时间,单位也是秒。

在ballon的根节点中,也可以修改播放下一句台词和跳过台词动画的快捷键,这里的跳过和刚才一样,都只是跳过一个字一个字蹦的阶段,并不会整个跳过对话,而且不存在覆盖关系,两个快捷键都会生效:

3. 保存二创

大家二创后,需要进行保存,并且要进行如下设置:

首先大家需要新建一个场景,叫什么都可以,我这里起名叫ballon_test,用于我们新气泡的测试,不然大家在插件中测试气泡时启动的还是默认气泡:

我们可以在插件的设置中看到,测试场景必须继承自BaseDialogueTestScene:

那我们给测试场景新建一个脚本,路径保存到一起:

让他继承一下这个类:

接着大家把二创好的场景从文件系统中按住ctrl拖拽到刚刚创建的ballon_test脚本中:

然后我们在ready中实例化(instantiate)一下这个ballon节点:

再然后我们把这个节点挂到主场景的节点树上:

之后我们调用这个ballon的start方法,方法内的参数大家感兴趣可以看一下源码,简单说一下就是BaseDialogueTestScene类将这两个值设置为了你在插件中正在使用的对话文件以及选中的Title

然后保存一下,在插件的设置中,把自定义测试场景换成我们刚才做的那个:

再运行一下就可以显示我们做好的二创气泡了:

四、新增功能之角色头像or立绘

在上一章中我们还没有实现随着切换角色,头像也跟着换的功能,这里我们来完成它,首先我们要把tag都加上,并且tag和文件名相同

接着我们到我们二创的气泡的脚本里:

大家先找到70多行的位置,这里是存放onready变量的地方:

右键Portrait,把它设置为作为唯一名称访问,这样如果我们调整它的层级关系之类的,不需要再重新拖拽到代码里了。

大家按住ctrl,把Portrait拖拽进来:

然后大家找到40多行左右的位置,这里是dialogue_line的属性代码(就是当这个变量被赋值时执行的代码,对应我们的气泡就是每次出现新台词会执行的代码),character_label相关代码的下方,这里是刚刚处理完角色名字的地方:

这里大家新建一个变量叫portrait_path用来表示头像的路径,内容就是头像的路径,大家可以拖拽任意一个头像文件到这个位置就可以自动生成路径(不要按ctrl),然后把文件名删掉改成%s。这个写法就是会把双引号后面的%跟着的变量(也就是dialogue_line.character变量)替换掉双引号中的%s。这个s代表String字符串变量,如果需要替换其他的变量就不能用s,详细的换法可以参考String的手册

这里dialogue.character的意思就是这一行台词对应的角色名,如果你一个角色只有一个头像的话可以直接这么写,就不用加tag了。然后把头像的文件名跟角色名一一对应上即可。

当然我相信独立游戏制作人不会这么甘于平庸,如果使用tag的方式就把这行代码改写为:

也就是获取character改为了获取tag“portrait”的值,很好理解吧?

接着我们用ResourceLoader.exists方法来判断这个文件是否存在,如果存在的话就加载到portrait节点的texture属性上,如果不存在的话就将texture清空:

这个时候再运行一下,可以正常切换了:

 

五、新增功能之对话音效(选修)

首先确保你的音效足够简短,因为一个字就对应了一声音效,可以使用音频编辑工具裁剪一下(如logic、库乐队、au、ce、cubase、fl、Studio one啥啥的都行),然后添加到sfx文件夹中:

我们再次来到我们二创的balloon场景中,在根节点上右键新建一个AudioStremPlayer节点(注意带2D和3D的是有空间效果的,如果你需要这个效果也可以选):

把音效放到这个节点的stream属性里:

给节点改个名字,我改成了SpeakSound:

依旧是在100行左右的位置,大家把SpeakSound节点也按住ctrl拖拽到balloon的代码里:

接下来大家选择DialogueLabel节点,在检查器旁边找到“节点”-“信号”:

大家双击这个spoke信号:

然后大家选择根节点,连接:

这样在ballon代码中,就会出来spoke信号触发的方法,spoke信号就是每出来一个字就触发一次,然后执行这个方法:

同时大家看到上方有个endregion了吗,大家最好把这个方法整体拖拽到endregion上方去写,因为这个是作者分的一块专门给信号用的代码区(region)。有个快捷键是选中一块代码,然后按alt+小键盘方向键,可以将代码整体平移~

接下来只要在这个方法里去播放音效就可以啦:

如果你想给每个角色适配不一样的音效的话,那还是到之前修改角色头像的代码位置,让它每一行都识别一下标签或角色,去同步修改SpeakSound节点的stream属性中的音频文件。或者改变语速什么的,也都可以通过在那个地方加上修改参数的代码来实现呢!

同时原视频作者也给我们展示了一下好玩的操作,比如可以随机修改speak_sound的pitch_scale属性,也就是随机音高,让它每次发音的音调都不一样,会更有说话的感觉:

randf_range的意思就是在括号中两个数字之间生成随机小数。

当然我们也可以在出现指定符号时不发出音效,注意最好也把中英文符号都加进去:

这里letter大家可以看到这个信号方法的括号里第一个参数就是letter,也就是当前这个字的意思。

此外,如果你不希望一个字一个字播放音效,想要给角色添加配音,那就不用这个信号方法了,直接在之前修改角色头像那个地方播放一次台词对应的音频就好啦,具体播放哪个音频你可以做个tag比如[#voice_number=100]之类的。

六、新增功能之按键提示(选修)

如果你想让玩家有更好的游戏体验,还可以提示玩家继续对话的快捷键。

在这里我们在ballon节点上右键创建一个Label子节点:

给它改个名字就叫Tip:

内容就修改成按Space继续:

将它拖拽到合适的位置:

我们再把Tip按住ctrl拖拽到balloon脚本中放onready变量的位置:

在balloon脚本中,我们可以看到在17行左右有一个变量叫is_waiting_for_input,也就是它是用来管理用户是否可以输入的flag标志位:

接下来我教大家如何创建一个变量属性,大家之前在修改立绘添加代码的位置就是处于dialogue_line的属性内:

可以看到,它跟方法的声明不一样,方法是func开头,但它和正常变量一样是var开头,代表dialogue_line本身也就是个变量。接着我们用一个冒号来声明它是一个DialogueLine类的变量,这里也和正常变量声明没有区别。

但是接下来它后面还有一个冒号,下面就开始写代码了,这就和普通的变量不一样了。

大家可以注意到是set开头的一段代码,并且继续往下翻可以看到一个get:

在这里呢,set就是对应的如果我们给这个变量(也就是dialogue_line)赋值时,会执行什么操作。get就是如果我们想获取这个变量的值时,它会给我们什么值。

这样的操作可以令变量的操作更加自由,可以在一个变量每次被使用时都执行一下set下面的方法,如果不用这个操作的话那我们可能只能用process一直检测变量有没有改变来实现了。

这个操作也就是叫“属性”。注意要和检查器里那些参数属性区分开!

那我们仿照这个写法,希望在is_waiting_for_input为true时,显示按键提示,反之为false时,隐藏按键提示:

这里可以注意一下,set括号里的值就是我们在给这个变量赋值时的值,名字是临时的我们可以随便取(比较通用的写法就是value)。比如我们后面调用is_waiting_for_input = true,那这个时候value就是true了。

set下面靠缩进那两行代码,就是每次被赋值时执行的代码,首先一定要保证is_waiting_for_input = value,不然它本身的值就不变了!然后我们让tip的visible(也就是是否可见)也等于这个value。

get下面的代码就是我们每次取值的时候用到的,这里return了一下is_waiting_for_input的值。效果就是假如我们新建一个变量来读取is_waiting_for_input的话:var test = is_waiting_for_input,test就可以正常得到is_waiting_for_input的值。虽然看上去好像多此一举,但是一旦你用了属性,那么变量的操作自由的代价就是什么都要自己写。

修改好了之后我们运行一下,就可以看到只有在台词结束的时候才会出现按键提示了!

七、在游戏中触发对话

1. 角色移动

接下来呢,我想实现一下角色可以在场景中移动,以实现我们真实玩游戏时触发对话的样子~

那我们来创建角色,首先我们点加号创建一个新的场景:

选择其他节点:

找到CharacterBody2D节点,选择创建:

给根节点改个名字,就叫Player:

ctrl+s保存一下,右键创建一个新文件夹用来保存场景文件,就叫Scenes吧~

双击进入文件夹,保存一下:

创建一个Sprite2D子节点:

改个名字,我习惯在节点原名加前缀哈~

接着我们把想要移动的角色图片放到BodySprite2D节点的Texture属性上:

我们再创建一个CollisionShape2D节点,用于做碰撞体积:

在检查器中新建一个Shape,我就直接选择矩形了:

调整一下大小,这次只做动画的实验,加这个碰撞体积仅仅是为了这个节点不报错,所以随便调,我们这次用不到。当然大家以后真的做平台跳跃游戏等涉及到物理碰撞的话,就必须好好调整(换了个图,不要介意):

选中根节点,然后点击创建脚本:

在这里路径我们选择src文件夹,模板勾选上CharacterBody2D的模板:

创建后我们可以看到,引擎自动帮我们生成了

接着我们可以注释掉跟跳跃相关的代码(或者直接删掉):

如果你有走路和待机动画的话,也可以在场景中创建一个animationplayer,在里面新建两个角色动画,做动画的操作大家可以参考我的桌宠教程:

如果你没有做动画的话,只需要添加如图所示代码,先把BodySprite2D拖拽到节点代码里,然后判断一下direction(也就是移动方向)来翻转一下BodySprite2D节点:

当然如果你的走路方向和图片方向反了,那就把false和true替换一下。

大家可以点击这个按钮运行一下当前场景(也就是角色),用小键盘左右移动一下看看是否正常:

动画怎么添加我这里就不细说了(因为我图省事儿做的不是规范操作),后面会出一期单独的教程来教大家角色如何移动,这里只是想快速跟大家展示一下对话插件!

最后我们来增加一个触发对话的区域,我们希望如果有可触发对话的角色或者物体进入到这个区域时,按下空格键(或者你设置的其他什么键)就能触发对话!

给Player添加一个Area2D节点,并给Area2D增加一个CollisionShape2D子节点。这个子节点的范围就是用来寻找对话触发器的:

改个名字:

给CollisionShape2D添加一个区域,这次的区域要比刚才的碰撞体积要大一些,因为我们不可能跟别人贴在一起了才能对话,中间能隔开一段距离比较优雅:

 

2. 对话触发器

下面呢,我们来做一个对话触发器,只要挂载触发器的节点,都可以被我们玩家触发对话,首先新建一个场景,选择其他节点里的Area2D:

改个名字,叫Actionable:

保存一下,注意路径:

新建一个脚本:

注意路径:

既然是触发器,那我们肯定需要一个能被触发出来的气泡,大家还是按住ctrl,把之前我们二创的气泡拖拽到代码里:

接下来我们需要设置一下要使用的对话文件,注意对话文件是DialogueResource类型的:

然后别忘了,还需要让触发器知道,从哪里开始播放对话,所以需要一个Title,这里可以给它一个默认值start:

这样在检查器里,我们也可以随时修改这两个值:

当触发器被触发时的动作,我们可以新建一个方法,就叫action:

如果你还有印象,应该还记得触发一个气泡的流程,首先我们实例化BALLOON:

接着我们让实例化的气泡成为场景的子节点:

最后一步稍微有点不一样,这次我们没有用默认参数,而是给了它我们准备好的对话文件和title:

当然如果你觉得这样还不满意,也可以让气泡场景加上@export,这样就可以给触发器自定义要触发的气泡样式了。如果你整个游戏只用了一个对话文本文件,也可以把对话文本文件改成默认值。

最后再介绍一个方法,就是如果你只有一个二创的气泡,那么触发器可以直接调用这个方法:

这一行代码可以直接顶替上面三行代码。然后在插件的设置Runtime里,可以把默认触发气泡换成我们设置好的二创气泡:

当然还是前一种方法自由度更高一些,看个人选择~

最后我们想让玩家可以使用触发器的话,再来打开Player的代码,把actionfinder节点先拖进来:

在最下面创建一个检测输入的方法:

这里我就直接检测默认的互动键ui_accept了:

大家可以在项目设置-键位映射里看到都是哪几个键,包括ui_cancel(记得打开右上角的“显示内置动作”):

接着我们新建一个变量叫actionables,让它去获取action_finder都跟哪些Area2D节点重叠了,这里获得的是一个数组:

接下来我们检测一下actionables的size是否大于0,也就是是否检测到了东西,如果有东西的话就执行首个actionable的action方法(我们刚才写的那个触发对话的方法):

为了确保action finder捕捉到的节点都是actionable这个对话触发器,而不是其他乱七八糟的东西,我们可以到actionbale节点上的检查器,找到Collision,点击右侧的三个点,点击编辑层名称:

我们选择一个没有使用到的层,比如这里我选择了Layer 3,并命名为actionables:

接着我们把actionable的Layer设为3,Mask全部取消。Layer的意思就是当前节点处于哪个层级,Mask的意思是它可以捕获到哪个层级的节点。我们需要让actionable处于它自己应该在的actionables层级,而我们不希望它捕捉到其他节点(别忘了,actionable节点是被捕获的,它被Player捕获,而不主动捕获其他节点!想不明白的话,可以这么看,玩家才是负责触发对话的人,而不是一个触发器跑过来主动跟玩家对话!当然你要做那种强制发起对话的npc,也没必要修改设置,可以直接手动执行以下触发器的action方法)。

同时,我们让Player的actionfinder节点的层级,改成Layer取消,Mask为3:

因为它不需要被其他人发现,所以Layer不需要设置。

3. 触发对话

全都OK了之后,下一步我们先搭建一个场景用来做游戏的舞台,根节点选node2d,改名叫World,保存到scenes文件夹中,这个大家应该轻车熟路了吧:

我先把背景放了进去,有没有无所谓,因为我们做教程需要好看一些:

右键World,选择实例化子场景:

把我们的角色添加进去:

调整一下大小:

我们右键一下World场景,设置为主场景,然后可以运行一下游戏左右走走试试:

接下来我们拖入第二个角色,直接拖图片进场景会自动帮我们创建好Sprite2D节点,调整好大小后我们给她命名为Npc(对不起法琳!):

我们右键Npc,实例化子场景:

选择actionable,然后打开:

给Actionable添加一个CollisionShape2D节点,并画好范围:

在Actionable节点里,我们可以把之前写好的对话文件拖拽到对应的属性里,Title默认就是我们想要的start就不改了:

然后咱们就可以运行一下看看效果,一切正常!反正我正常了,如果你没有正常显示,那可以看看哪一步做差了,实在找不到原因就来找我,我帮你看:

按照原视频作者的剧本里,应该是玩家主动过去找Npc,问Npc需不需要苹果,如果玩家自己没有苹果的话就去书上摘一个,那我们还需要一棵树。物品跟Npc一样,也是Actionable加一个CollisionShape2D:

如果你不希望树挡住玩家,就把玩家放到最下面:

在这里我重写了剧本,相信经过前面的学习,你已经能看懂这篇对话了:

值得注意的是,我新增了给苹果树互动的内容,对应的就是苹果数量+1:

我们在苹果树的Actionable节点中把这个title和对话文件加上去:

当然别忘了把苹果初始数量也改成0:

这样运行一下就可以基本实现所有对话效果了~

4. 更丰富的演出效果:

前面第二章还没有讲完的执行方法函数,现在可以继续来讲了,首先我们要在World节点上创建一个脚本:

记得保存到src:

创建好后,我们把Player拖拽进World脚本:

然后我们在Player的脚本里创建一个方法,你可能已经困了,但还是提醒你一下,这里是Player的脚本,不是World脚本

大家可以简单看一下这个方法,首先我让她水平翻转一下,然后等待1秒,再翻转回来,再等待0.5s,可以塑造一个震惊的效果,方法名也叫amazed。

然后我们把这个方法写到对话里就可以了~因为我们已经在场景根节点World的脚本里声明了player,所以在这里我们可以直接调用player的方法:

还有大家运行时会发现,当代码处于await时,对话会被自动隐藏,这可以更方便我们做演出效果~但是有的情况下,我们还是希望执行的方法不要阻塞我们的对话,这时候只要在do后面加一个感叹号就可以无视阻塞了:

同理,我也让Npc拿到苹果后有一个手握苹果的动作(像展示里那样),因为不是谁都有这么多素材,所以我就不带着大家做了,我相信大家应该都会了!

最后如果大家希望玩家不要在对话时随便走动,有很多方法实现,最直观的方法就是做一个flag标志位,当触发对话时设为true,结束对话后是false,然后在玩家移动方法里判断这个值是不是false,如果是false就正常执行移动的代码,如果是true就直接return。这个我也不带着大家做了~

后记

又是超长的一篇完整教程啊~要了老命了,哈哈哈!大家后续可以多研究一些对话效果,比如特效字体呀,动态头像呀,更丰富的动效呀之类的,做完之后记得艾特我交作业哦!前几期教程的热度都不是很好,还是希望大家能多多转发或者帮我宣传一下~同时也请大家支持一下插件的作者Nathan Hoad,点击插件右上角的爱心就可以向他捐款了~

我们下期再见,bye~

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值