Unity简单对话系统实现

本文详细介绍了如何在Unity中构建一个包含多个对话模块的系统,包括创建DialoguePanel组件、DialogueData数据结构、DialogueDataListSO管理对话数据,以及DialogueSystem的单例模式实现和选项生成。通过实例代码展示了如何处理对话流程、选项选择和立绘位置切换。
摘要由CSDN通过智能技术生成


前言

思路:将每段对话分为一个单独的对话模块,每段对话模块拥有自己独有的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简单对话系统的优化

Unity 对话编辑器是一种强大的工具,用于创建游戏中的角色对话和交互。它提供了一个可视化的界面,使开发者能够轻松地设计和管理对话内容。 Unity 对话编辑器的主要功能包括创建对话流程、添加对话内容和选择角色的行为。在对话流程中,开发者可以设置不同的对话节点,并通过连接这些节点来构建对话的逻辑流程。在每个对话节点中,可以添加对话内容,包括对话文本、语音、图片等,以丰富玩家的游戏体验。此外,开发者还可以为角色设置不同的行为,例如动画、特效和触发条件,以增加对话的互动性。 使用 Unity 对话编辑器,开发者可以方便地对对话内容进行管理和修改。通过可视化的界面,可以直观地编辑和组织对话的结构和内容。同时,对话编辑器还支持多语言翻译和本地化,开发者可以在同一个工具中管理不同语言的对话文本,为不同地区的玩家提供更好的游戏体验。 Unity 对话编辑器的优势在于它与 Unity 强大的游戏开发生态系统的集成。与 Unity 其他组件和工具的无缝结合,开发者可以更加高效地创建和实现游戏中的对话和交互。此外,Unity 的大量资源和社区支持也为开发者提供了丰富的对话编辑器扩展和教程,使其更易于上手和使用。 总而言之,Unity 对话编辑器是一项重要的游戏开发工具,它为开发者提供了创建和管理游戏中角色对话的便捷方式。通过可视化的界面和灵活的功能,它能够帮助开发者实现丰富多样的对话内容和交互体验,提升游戏的质量和吸引力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值