在解谜类游戏中,与npc的对话是一个基础且常用的功能。通常来说,在与npc的对话中玩家可以获取一些有价值的信息并对之后的游戏有一定的导向作用。此外,在玩家获取对应物品前后,与npc的对话内容也会发生相应改变。因此,我们需要将对话系统进行封装,以便于在不同的npc身上进行使用,同时要预留接口,后期可以增加或修改对话内容。
这里我们以Cotton Puzzle为例,将对话系统拆分为数据、逻辑和UI三部分来实现。在游戏中,获取物品前后与老太太的对话显示如下:
一、数据
首先,添加数据创建目录
//DialogData.cs[CreateAssetMenu(fileName ="DailogData", menuName ="Dialog/DailogData")]
创建列表用于存储对话内容
//DialogData.cspublicclassDialogData:ScriptableObject{publicList<string> dialogList;}
之后,单机右键依次选择Create -> Dialog -> DialogData创建一个空的数据集
在所创建的数据集中输入对话内容,如下:
二、逻辑
利用栈来存储对话数据,每次在需要进行对话时首先将当前状态设置为isTalking并禁用场景切换的操作,之后每一次点击老奶奶便从栈中弹出一条对话内容进行显示。在完成对话之后将isTalking设置为false并重新将数据压入栈中。
1.定义数据存储和状态变量
//DialogController.cspublicDialogData dialogEmpty;publicDialogData dialogFinish;privateStack<string> dialogEmptyStack =newStack<string>();privateStack<string> dialogFinishStack =newStack<string>();publicbool isTalking;
2.在游戏一开始时将数据压入栈中
//DialogController.csprivatevoidAwake(){FillDialogStack();}publicvoidFillDialogStack(){for(int i=dialogEmpty.dialogList.Count-1;i>=0;i--){
dialogEmptyStack.Push(dialogEmpty.dialogList[i]);}for(int i = dialogFinish.dialogList.Count -1; i >=0; i--){
dialogFinishStack.Push(dialogFinish.dialogList[i]);}}
3.定义协程,根据不同状态显示不同对话内容
publicvoidShowDialogEmpty(){if(!isTalking)StartCoroutine(DialogRoutine(dialogEmptyStack));}publicvoidShowDialogFinish(){if(!isTalking)StartCoroutine(DialogRoutine(dialogFinishStack));}privateIEnumeratorDialogRoutine(Stack<string> data){
isTalking =true;//Debug.Log("DialogRoutine协程开始");if(data.TryPop(outstring result)){//Debug.Log("开始对话");
EventHandler.CallShowDialogEvent(result);yieldreturnnull;
EventHandler.CallGameStateChangedEvent(GameState.Pause);//暂停游戏}else{
EventHandler.CallShowDialogEvent(string.Empty);FillDialogStack();
EventHandler.CallGameStateChangedEvent(GameState.GamePlay);//暂停游戏}
isTalking =false;}
三、UI
在DialogUI 中注册ShowDialogEvent ,当对话未完成时(即dialog 不为空)将panel设置为active,当对话结束以后便关闭panel。
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.UI;publicclassDialogUI:MonoBehaviour{publicGameObject panel;publicText dialogText;privatevoidOnEnable(){
EventHandler.ShowDialogEvent += ShowDialog;}privatevoidOnDisable(){
EventHandler.ShowDialogEvent -= ShowDialog;}privatevoidShowDialog(string dialog){if(dialog !=string.Empty)
panel.SetActive(true);else
panel.SetActive(false);
dialogText.text = dialog;}}
版权归原作者 float_freedom 所有, 如有侵权,请联系我们删除。