各位同学,大家好今天我要开始自学对话系统了,今天不准备自己造轮子,利用Godot的Dialogic 2.0插件来玩主人公与NPC的对话。先看一下最终效果。
开始行动。
一、配置Dialogic 2.0环境
1.首先我们从Releases · dialogic-godot/dialogic (github.com) 网址下载Dialogic 2.0代码,下载位置在该页面的最下端,如图:
2.下载完成解压后,将目录下的addons文件考到我们的项目的根目录下。
3.在Godot的编辑器中的菜单选择项目->项目设置,在弹出的项目设置框中切换到插件选项卡,然后勾选Dialogic插件的启用选项,估计是这个插件比较大的缘故,打钩的时候会有卡顿,大家不要着急,操作过程如下:
4.这样操作后,会在Godot编辑器的上方出现Dialogic标签,说明我们的插件安装成功。
二、添加NPC
1.新建场景和节点
首先我们新建场景选择CharacterBody2D作为根节点,命名为NPC,保存到Scenes目录下。为根节点依次建立Sprite2D、AnimationPlayer、Area2D和CollisionShape2D节点,然后给Area2D节点添加CollisionShape2D子节点,节点目录情况如下:
2.设置Sprite2D节点属性
将我们准备好的NPC图片素材拖入到Sprite2D节点检查器下的Texture属性下。将该节点的Animation->Hframes设置为6;Vframes设置为1,如下:
这样我们的Sprite2D节点就会显示该图素材的第一帧了,这样设置主要是为AnimationPlayer节点做准备。
3.设置AnimationPlayer节点
在AnimationPlayer节点的动画面板中选择动画按钮->新建,然后在创建新动画框中输入Default名称,单击确定按钮。
将动画帧调整到第一帧,然后在Sprite2D检查器Frame属性后面的关键帧按钮依次单击,将6个关键帧插入到动画中,操作过程如下:
然后在动画面板中开启动画的循环和自动播放功能,最后结果如下:
这样我们的NPC就有了一个动画。
4.设置Area2D节点
这个节点功能用于主人公进入NPC的监控范围,会在NPC顶部显示一个有话要说的小图标。首先我们将Area2D重新命名为ShowDialogIco,然后调整子节点CollisionShape2D大小,用于监控主人公是否进入范围。
在ShowDialogIco检查器中将Collision->Layer设置为Object层,Mask设置为Player,这样表示为该节点主动与主人公发生碰撞。
5.添加对话框提示
为根节点添加Sprite2D节点,命名为IcoSp,添加AnimationPlayer命名IcoAnimP。将placeholder.png素材托人到IcoSp节点检查器下的Texture属性下,Node2D->Transform下的Position属性设置为5,-21;Scale属性设置为0.3,0.3,如下:
在IcoAnimP动画面板中,新建动画命名为Default,将IcoSp的Position(5,-21)添加到0,1帧和1.0帧;将IcoSp的Position(5,-25)添加到0.2帧和0.8帧;将IcoSp的Scale(0.3,0.3)添加到0,1帧和1.0帧;将IcoSp的Scale(0.35,0.35)添加到0.2帧和0.8帧,并开启循环动画功能。具体情况如下:
最后将IcoSp的Visible设置为不启用,这样的目的是默认的时候不显示对话提示图标,用代码控制主人公进入制定范围后显示提示图标。
5.添加代码
选择根节点,单击添加代码按钮为根节点添加代码,保存到Scripts目录下,命名为NPC.gd。
选择ShowDialogIco节点,在其节点信号中双击body_entered(body:Node2D)节点在连接信号到方法面板中选择NPC,最后单击连接按钮,这样就会在NPC代码中添加_on_show_dialog_ico_body_entered(body)函数,操作过程如下:
!
该函数表示进入ShowDialogIco范围调用,修改代码_on_show_dialog_ico_body_entered,当主人公进入NPC范围内图标显示,并播放动画:
func _on_show_dialog_ico_body_entered(body):
if body.name == "Player":
$IcoSp.visible=true
$IcoAnimP.play("Default")
pass
选择ShowDialogIco节点,在其节点信号中双击body_exited(body:Node2D)节点在连接信号到方法面板中选择NPC,最后单击连接按钮,这样就会在NPC代码中添加_on_show_dialog_ico_body_entered(body)函数,该函数表示离开ShowDialogIco范围调用,修改该函数代码,当主人公离开NPC范围后,对话提示图标隐藏,动画停止播放。
func _on_show_dialog_ico_body_exited(body):
if body.name == "Player":
$IcoSp.visible=false
$IcoAnimP.stop()
pass
三、建立对话系统
1.新建文件夹
在文件系统中,右键单击res://弹出菜单选择新建->新建文件夹,然后在创建文件夹对话框中输入Dialog,单击确定按钮,这样就新建Dialog文件夹了,用于存放Dialogic有关文件。
2.新建TimeLine
切换到Dialogic面板,并单击TimeLine选项卡,然后在面板中Create New timeline按钮或者单击上方选项卡右侧的添加TimeLine按钮。
在弹出的Create new timeline对话框中选择Dialog文件夹,然后输入NPCtimeline名称,单击保存按钮保存。
然后在NPCtimeline面板中单击三次Text按钮,然后依次录入文本信息,前两个选择NPCcharacter,后一个选择PlayerCharacter,这两个Character市在步骤3中创立,只有步骤3操作完成才能进行选择,最后结果如下图:
3.新建Charater
第一是新建NPC,切换到Character选项卡,然后单击Create new Character按钮。
在弹出框中选择保存位置为Dialog文件夹,名称设置为NPCCharacter后保存。
然后在设置面板中Display Name为怪老头,颜色设置为绿色;Style选择DefaultStyle(这个样式是第4步的时候新建的样式,所以在第4步完成以后才能选择)。
在Portraits面板中单击Add Porait按钮,名称设为NPC,然后在右侧的Portrait Settings中Image选择怪老头的头像,最后结果如下图:
第二是新建Player。 单击选项卡上方的Add Character按钮,在在弹出框中选择保存位置为Dialog文件夹,名称设置为PlayerCharacter后保存。然后在设置面板中Display Name为晓龙,颜色设置为黄色;Style选择PlayerStyle(这个样式是第4步的时候新建的样式,所以在第4步完成以后才能选择)。
在Portraits面板中单击Add Porait按钮,名称设为,然Player后在右侧的Portrait Settings中Image选择主人公的头像,最后结果如下图:
4.新建样式
一是新建DefaultStyle样式。 切换到样式选项卡,在样式选项卡单击Add layout style按钮在弹出菜单中选择Premade style。
在弹出的Style Browser窗口中选择Speaker TextBox Style,然后单击Use按钮。
然后在弹出的对话框中选择保存位置为Dialog文件夹,名称设置为DefaultStyle后保存。最后是这个样子
切换到Textbox with Portrait 选项卡下面的Name Label选项卡,Color属性下面的Mode选择Character Color,这样NPCcharacter里面设置的绿色才起作用。
二是新建PlayerStyle样式。 这个过程与新建DefaultStyle样式类似,在样式选项卡单击Add layout style按钮在弹出菜单中选择Premade style。在弹出的Style Browser窗口中选择Speaker TextBox Style,然后单击Use按钮。
四、代码调用对话
切换到NPC跟目的的代码状态,首先设置一个变量IsDialog表示是否进行对话,默认值为false,当主人公进入NPC对话范围内,将IsDialog设为true;离开NPC对话范围将IsDialog设为false,具体代码如下:
extends CharacterBody2D
@export var playerPositon:CharacterBody2D
var IsDialog=false
func _physics_process(delta):
if IsDialog:
if Input.is_action_just_pressed("dialog"):
if Dialogic.current_timeline != null:
return
var layout = Dialogic.start('NPCtimeline')
get_viewport().set_input_as_handled()
pass
move_and_slide()
func _on_show_dialog_ico_body_entered(body):
if body.name == "Player":
$IcoSp.visible=true
$IcoAnimP.play("Default")
IsDialog=true
pass
func _on_show_dialog_ico_body_exited(body):
if body.name == "Player":
$IcoSp.visible=false
$IcoAnimP.stop()
IsDialog=false
pass