目录
前言
思路:将每段对话分为一个单独的对话模块,每段对话模块拥有自己独有的ID和几句单独的对话,每段对话中自己定义是否含有选择,每个选择拥有与对话模块对应的相同ID(自己决定选择后跳转的对话模块),点击后跳转到对应对话模块,最后有一个用于管理所有对话模块的管理中心用于存储所有的对话模块。
一、场景搭建
二、创建DialoguePanel
1、创建用于获得组件的代码
using UnityEngine;
using UnityEngine.UI;
public class DialoguePanel : MonoBehaviour
{
[Tooltip("说话者")]public Text speakerName;
[Tooltip("说话内容")]public Text speech;
[Header("------")]
[Tooltip("说话角色的立绘或者头像")]public Image rowImage;
[Header("------")]
[Tooltip("继续下一句话按钮")]public Button continueSpeechBtn;
[Header("------")]
[Tooltip("生成选项预制体")]public ChooseButton chooseButtonPre;
[Header("------")]
[Tooltip("选择按钮的生成位置")]public Transform chooseParent;
[Tooltip("角色立绘位置")]public Transform rowDetailsTrans;
}
2、将其挂载在对话面板的Canvas物体上进行赋值
三、创建对话数据DialogueData
代码部分:
using System;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu( menuName = "对话/DialogueData")]
public class DialogueData : ScriptableObject
{
public int ID;//存储在字典中的ID
public List<Dialogue> dialogueList;
}
[Serializable]
public class Dialogue//对话
{
public Row row;//枚举数据 区别立绘出现在左边或者右边
public string speakerName;
[TextArea(5,4)]
public string speech;
public List<Choose> chooseList = new List<Choose>();//对话是否有选项
}
[Serializable]
public class Choose//选项
{
public int ID;//选项的ID
public string chooseBtnText;
}
数据部分:
在此对话的最后部分创建几个选项
创建几个对应选项的对话数据
四、创建管理对话数据DialogueDataListSO
代码部分:
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "对话/DialogueDataListSO")]
public class DialogueDataListSO : ScriptableObject
{
public List<DialogueData> dialogueDataList;
private Dictionary<int,DialogueData> DialogueDataDic;
public Dictionary<int,DialogueData> dialogueDataDic=> DialogueDataDic;
public void Initialization()//初始化字典,并将dialogueDataList中的dialogueData存入
{
DialogueDataDic = new Dictionary<int, DialogueData>();
foreach (var dialogueData in dialogueDataList)
{
DialogueDataDic.Add(dialogueData.ID,dialogueData);
}
}
}
字典的作用是在出现选项时,通过对应的ID跳转到对应的DialogueData
数据部分:
五、创建对话的业务中心DialogueSystem
1、将其写成单例模式,便于使用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DialogueSystem : MonoBehaviour
{
private static DialogueSystem instance;
public static DialogueSystem Instance => instance;
[Tooltip("对话面板")]public DialoguePanel dialoguePanel;
[Tooltip("对话数据列表")]public DialogueDataListSO dialogueDataListSO;
[Tooltip("当前处于第几句对话")]public int currentSpeechCount;
private DialogueData dialogueData;//从对话数据列表中获得单个对话数据
private void Awake()
{
if(instance != null)
{
Destroy(this);
}
else
{
instance = this;
}
dialogueData = dialogueDataListSO.dialogueDataList[0];//从存储的对话的第一个开始
dialogueDataListSO.Initialization();//初始化字典
SyncDialogueInformation(currentSpeechCount);
}
}
2、同步对话信息,在Awake中执行一次
public void SyncDialogueInformation(int speechCount)//同步对话信息
{
dialoguePanel.speakerName.text = dialogueData.dialogueList[speechCount].speakerName;
dialoguePanel.speech.text = dialogueData.dialogueList[speechCount].speech;
}
3、此时返回Unity启动,便会发现面板中的数据同步到对话的数据文件
4、点击继续实现更新对话
public static void UpdateDialogueSpeech()//更新对话
{
instance.currentSpeechCount++;
if (instance.currentSpeechCount >= instance.dialogueData.dialogueList.Count)
{
instance.currentSpeechCount = 0;
}
instance.SyncDialogueInformation(instance.currentSpeechCount);
}
对话存储在列表中,点击继续将对应的下标+1
此时返回Unity启动点击继续便会先发对话实现了继续下一句
5、生成选项,对话是否有选择
按钮代码:
using UnityEngine;
using UnityEngine.UI;
public class ChooseButton : MonoBehaviour
{
public Text chooseText;//按钮显示内容
public Button chooseBtn;
public int ID;//按钮ID
private void Awake()
{
chooseBtn.onClick.AddListener(UpdateTalk);
}
public void UpdateTalk()
{
//点击执行部分
}
}
生成选项:
public void InstanceChooseBtn(Transform transform)//生成选项
{
ChooseButton chooseButton;
if (dialoguePanel.chooseButtonPre != null) // 判空逻辑
{
for (int i = 0; i < dialogueData.dialogueList[currentSpeechCount].chooseList.Count; i++)
{
chooseButton = Instantiate(dialoguePanel.chooseButtonPre, transform);
chooseButton.chooseText.text = dialogueData.dialogueList[currentSpeechCount].chooseList[i].chooseBtnText;
chooseButton.ID = dialogueData.dialogueList[currentSpeechCount].chooseList[i].ID;
//将选项按钮中的ID同步于当前对话中的选项的ID
dialoguePanel.continueSpeechBtn.gameObject.SetActive(false);//生成选项时关闭继续按钮
}
}
else
{
Debug.LogError("chooseButtonPre 为空");
}
}
原理:循环当前对话内的chooseList中是否有选项,如果有就将其生成出来
将其放在更新对话中执行,传入的transform参数为按钮生成的位置
public static void UpdateDialogueSpeech()//更新对话
{
instance.currentSpeechCount++;
if (instance.currentSpeechCount >= instance.dialogueData.dialogueList.Count)
{
instance.currentSpeechCount = 0;
}
instance.SyncDialogueInformation(instance.currentSpeechCount);
instance.InstanceChooseBtn(instance.dialoguePanel.chooseParent);
}
6、点击选项时执行逻辑
public void ChooseClickUpdateDialogueSpeech(int alpa)//点击时,更新对话 需要在生成按钮时就将按钮对应的List传入
{
dialogueData = dialogueDataListSO.dialogueDataDic[alpa];//根据对应ID选择字典中的对话数据
dialoguePanel.continueSpeechBtn.gameObject.SetActive(true);//点击选项后开启继续按钮
ClearChoices();
}
public void ClearChoices()// 销毁之前的选择按钮
{
ChooseButton[] chooseBtns = dialoguePanel.chooseParent.GetComponentsInChildren<ChooseButton>();
foreach (ChooseButton choice in chooseBtns)
{
Destroy(choice.gameObject);
}
}
添加到按钮中
using UnityEngine;
using UnityEngine.UI;
public class ChooseButton : MonoBehaviour
{
public Text chooseText;
public Button chooseBtn;
public int ID;
private void Awake()
{
chooseBtn.onClick.AddListener(UpdateTalk);
}
public void UpdateTalk()
{
DialogueSystem.Instance.ChooseClickUpdateDialogueSpeech(ID);//根据传入的ID更新对话数据
DialogueSystem.UpdateDialogueSpeech();//更新对话
}
}
7、根据row的位置更换显示位置,在每次更新对话时执行
public void SwitchPosition()//根据row的位置更换显示位置
{
switch (dialogueData.dialogueList[currentSpeechCount].row)
{
case Row.left :
dialoguePanel.rowDetailsTrans.localPosition = new Vector3(-567,87,0);
break;
case Row.right :
dialoguePanel.rowDetailsTrans.localPosition = new Vector3(567,87,0);
break;
}
}
public static void UpdateDialogueSpeech()//更新对话
{
instance.currentSpeechCount++;
if (instance.currentSpeechCount >= instance.dialogueData.dialogueList.Count)
{
instance.currentSpeechCount = 0;
}
instance.SyncDialogueInformation(instance.currentSpeechCount);
instance.InstanceChooseBtn(instance.dialoguePanel.chooseParent);
instance.SwitchPosition();
}
此时便已实现简单的对话加选项功能
可查看实现效果
后续使用过程中发现了一些问题,可查看优化Unity简单对话系统的优化