上海古都建筑设计集团,上海办公室装修设计公司,上海装修公司高质量的内容分享社区,上海装修公司我们不是内容生产者,我们只是上海办公室装修设计公司内容的搬运工平台

【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新)

guduadmin321月前

文章目录

  • 先看看实现的最终效果
  • 前言
  • 素材
  • 前期准备工作
    • 1. 简单绘制地形
    • 2. 绘制对话框
    • 3. 配置人物动画
    • 4. 实现简单的控制人物移动
    • 控制对话框的显示隐藏
    • 定义对话内容
    • 实现简单的对话功能
    • 逐字打印效果
    • 按下按键快速显示文本
    • 实现多个NPC配置不同对话
    • 扩展
      • TextAsset 读取文档文件
      • 实际应用
      • 修改字体样式(2023/12/26补充)
      • 补充
      • 源码
      • 参考
      • 完结

        先看看实现的最终效果

        【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第1张

        前言

        之前的对话系统因为存在一些错误和原作者不允许我分享,所以被我下架了,而且之前对话系统确实少了一些功能,比如最基本的逐字打印功能,原本来是打算后面补充的。

        对话系统在游戏中实现太常见了,所以我又重新去找了一些对话系统的课程进行学习,把实现过程和笔记分享出来,后面肯定会用到。

        本文是参考b站麦扣老师比较老的课程了,我已经看完了,后面发现缺失了挺多功能的:

        • 比如扩展性不好,多NPC很难将对话分开
        • 快速显示的实现过于麻烦了
        • 对话框显示在世界坐标,UI无法适配屏幕的变化
        • 文本只支持显示内容,不支持显示角色名称和人物的不同表情变化
        • 缺少控制某些文字样式变化,比如修改颜色

          所以我改动的地方可能比较多,因为我想实现的是一个通用的对话脚本,可以很方便的对多个NPC绑定不一样的对话内容,当然,麦扣老师的视频链接我会放在文章底部,感兴趣的也可以去看看原版,对照着学习!

          素材

          素材下载地址:

          https://bakudas.itch.io/generic-rpg-pack

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第2张

          前期准备工作

          1. 简单绘制地形

          关于TileMap的使用,这里就不再过多介绍了,感兴趣的可以查看我之前的文章:

          【Unity小技巧】Unity2D TileMap的探究(最简单,最全面的TileMap使用介绍)

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第3张

          2. 绘制对话框

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第4张

          3. 配置人物动画

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第5张

          4. 实现简单的控制人物移动

          新建脚本,简单的控制人物的移动和动画切换

          public class Player : MonoBehaviour
          {
              [Header("移动速度")]
              public float speed;
              Animator animator;
              Vector3 movement;
              
              void Start()
              {
                  animator = GetComponent();
              }
              void Update()
              {
                  //移动
                  movement = new Vector3(Input.GetAxisRaw("Horizontal") * Time.deltaTime * speed, Input.GetAxisRaw("Vertical") * Time.deltaTime * speed, transform.position.z);
                  transform.Translate(movement);
                  //动画
                  if (movement != Vector3.zero)
                  {
                      animator.SetBool("run", true);
                  }else{
                      animator.SetBool("run", false);
                  }
                  //翻面
                  if(movement.x>0){
                      transform.localScale = new Vector3(1, 1, 1);
                  }
                  if(movement.x<0){
                      transform.localScale = new Vector3(-1, 1, 1);
                  }
              }
          }
          

          效果

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第6张

          控制对话框的显示隐藏

          新增脚本TalkButton,控制NPC对话提示和对话框的显示和隐藏

          public class TalkButton : MonoBehaviour
          {
              private GameObject tipsButton;//对话提示按钮
              [Header("对话框")]
              public GameObject dialogBox;
              
              private void OnTriggerEnter2D(Collider2D other)
              {
                  tipsButton = other.transform.Find("对话提示").gameObject;
                  tipsButton.SetActive(true);
              }
              
              private void OnTriggerExit2D(Collider2D other)
              {
                  tipsButton.SetActive(false);
                  dialogBox.SetActive(false);
              }
              
              private void Update()
              {
                  if (tipsButton != null && tipsButton.activeSelf && Input.GetKeyDown(KeyCode.R))
                  {
                      dialogBox.SetActive(true);
                  }
              }
          }
          

          效果

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第7张

          定义对话内容

          新建DialogNode,定义每段对话的各种属性

          // 代表了一个对话节点。
          [Serializable]
          public class DialogNode
          {
              [Header("角色的名字")]
              public string name;
              [Header("角色的头像")]
              public Sprite sprite;
              
              [TextArea, Header("对话的内容")]
              public string content;
          }
          

          新建Dialogue脚本,继承ScriptableObject,这样我们就可以在界面方便的新建各种对话了

          // 表示一段对话
          [CreateAssetMenu(menuName="创建对话" ,fileName = "对话")]
          public class Dialogue : ScriptableObject 
          {
              // 对话节点
              public DialogNode[] dialogNodes;
          }
          

          回到界面,创建各种对话,并配置对话内容

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第8张

          实现简单的对话功能

          定义NPC脚本

          public class NPC : MonoBehaviour {
              [Header("对话内容")]
              public Dialogue dialogue;
          }
          

          给不同NPC挂载不同的对话

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第9张

          修改TalkButton,获取对应的NPC对话内容,并修改为单例,方便其他地方调用dialogue对话内容

          [NonSerialized]
          public Dialogue dialogue;//对话内容
          //单例
          public static TalkButton instance;
          private void Awake()
          {
          	if(instance == null)
          	{
          		instance = this;
          	}else{
          		if(instance != this){
          			Destroy(gameObject);
          		}
          	}
          	DontDestroyOnLoad(gameObject);
          }
          	
          private void OnTriggerEnter2D(Collider2D other)
          {
              dialogue = other.GetComponent().dialogue;
              //。。。
          }
          

          新增DialogSystem脚本,挂载在对话框上

          public class DialogSystem : MonoBehaviour
          {
              private Dialogue dialogue;//对话内容
              //索引
              private int index;
              //对话内容框
              TextMeshProUGUI dialogueContent;
              //名称框
              TextMeshProUGUI dialogueName;
              //头像框
              Image dialogueImage;
              private void Awake() {
                  gameObject.SetActive(false);    
              }
              private void OnEnable()
              {
                  dialogue = TalkButton.instance.dialogue;
                  dialogueContent = transform.Find("内容").GetComponent();
                  dialogueName = transform.Find("名字").GetComponent();
                  dialogueImage = transform.Find("头像").GetComponent();
                  //设置人物头像保持宽高比,防止压缩变形
                  dialogueImage.preserveAspect = true;
                  
                  index = 0;
                  Play();
              }
              private void Update()
              {
                  if (Input.GetKeyDown(KeyCode.R) && dialogue != null)
                  {
                       //对话播放完,关闭对话
                        if (index == dialogue.dialogNodes.Length)
                        {
                            gameObject.SetActive(false);
                            index = 0;
                        }
                        else
                        {
                            //开始对话
                            Play();
                        }
                  }
              }
              // Play 函数用于开始播放对话。
              private void Play()
              {
                  // 获取当前对话节点,并更新索引值。
                  DialogNode node = dialogue.dialogNodes[index++];
                  // 设置对话内容、角色名称和头像
                  dialogueContent.text = node.content;
                  dialogueName.text = node.name;
                  dialogueImage.sprite = node.sprite;
              }
          }
          

          效果

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第10张

          逐字打印效果

          修改DialogSystem,创建携程实现逐字打印效果,为了防止字体发生错乱我们要加判断,每一行执行完成后才可以继续进入下一段对话

          [SerializeField, Header("目前逐字打印速度")]
          private float textSpeed;
          bool isDialogue;//是否正在对话
          private void OnEnable()
          {
              isDialogue = false;
              // 。。。
          }
          private void Update()
          {
              if (Input.GetKeyDown(KeyCode.R) && dialogue != null)
              {
                  if (!isDialogue)
                  {
                      //对话播放完,关闭对话
                      if (index == dialogue.dialogNodes.Length)
                      {
                          gameObject.SetActive(false);
                          index = 0;
                      }
                      else
                      {
                          //开始对话
                          Play();
                      }
                  }
              }
          }
          // Play 函数用于开始播放对话。
          private void Play()
          {
              // 获取当前对话节点,并更新索引值。
              DialogNode node = dialogue.dialogNodes[index++];
              // 设置对话内容、角色名称和头像
              // dialogueContent.text = node.content;
              StartCoroutine(SetTextUI(node));
              dialogueName.text = node.name;
              dialogueImage.sprite = node.sprite;
          }
          //逐字打印
          IEnumerator SetTextUI(DialogNode node)
          {
              isDialogue = true;
              dialogueContent.text = "";
              for (int i = 0; i < node.content.Length; i++)
              {
                  dialogueContent.text += node.content[i];
                  yield return new WaitForSeconds(textSpeed);
              }
              isDialogue = false;
          }
          

          效果,记得在面板配置textSpeed值,我这里定为0.1

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第11张

          按下按键快速显示文本

          修改DialogSystem,我们通过控制文本播放速度实现

          private float startTextSpeed;//开始逐字打印速度
          private void OnEnable()
          {
          	//...
          	startTextSpeed = textSpeed;
          }
          private void Update()
          {
              if (Input.GetKeyDown(KeyCode.R) && dialogue != null)
              {
                  //如果正在对话,再次按下R,快速显示所有对话
                  if (isDialogue)
                  {
                       textSpeed = 0;
                  }
                  else
                  {
                      //回复文本速度
                      textSpeed = startTextSpeed;
                      //对话播放完,关闭对话
                      if (index == dialogue.dialogNodes.Length)
                      {
                          gameObject.SetActive(false);
                          index = 0;
                      }
                      else
                      {
                          //开始对话
                          Play();
                      }
                  }
              }
          }
          

          效果

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第12张

          实现多个NPC配置不同对话

          配置多个NPC,给每个NPC配置不同的对话

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第13张

          最终效果

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第14张

          扩展

          麦扣的课程用的是TextAsset读取txt文本,这种方式因为不方便配置显示角色名称和头像表情变化,所有我放弃了,但是还是补充一下TextAsset的用法,因为他可能在其他地方可以应用

          TextAsset 读取文档文件

          TextAsset 是把一种某种格式的文件输入到我们的游戏项目当中,然后它可以帮助我们转换这里边的这个文本

          它可以支持的类型有:

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第15张

          它里边也有一个自带的一个参数的方法,就是.text,它会把整个文件转换成一个单独的字符型的数据

          实际应用

          比如这样的文本

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第16张

          代码读取文本

          public class DialogSystem : MonoBehaviour
          {
              [Header("文本文件")]
              public TextAsset textFile; // 用于存储对话文本的文本文件
              public int index; // 对话索引,用于跟踪当前对话位置
              List textList = new List(); // 存储从文本文件中读取的对话内容的列表
              void Start()
              {
                  GetTextFromFile(textFile);
              }
              void GetTextFromFile(TextAsset file)
              {
                  var lineData = file.text.Split('\n'); // 将文本文件按行分割
                  foreach (var line in lineData)
                  {
                      textList.Add(line); // 将每行对话文本添加到对话内容列表中
                  }
              }
          }
          

          修改字体样式(2023/12/26补充)

          最近有小伙伴来找我,说实现修改某些字体颜色或者突出某些文本如何做?

          其实也很简单,如下,这里就再补充一下。

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第17张

          这种语法叫做 Rich Text 标记,在 Unity 中可以用于富文本显示。除了 标记外,还有其他一些标记可以用于修改文本的样式、大小、字体等,比如:

          红色
          红色
          红色
          加粗
          斜体
          大号
          

          代码控制

          // 使用 Rich Text 标记修改文本内容
          myText.text = "这是一段 红色 的文本,加粗并且变为 大号 字体。";
          // 改变文本字体
          Font myFont = Resources.GetBuiltinResource("Arial.ttf");
          myText.font = myFont;
          

          这里我们要修改某段对话的文字样式,就很简单了

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第18张

          补充

          逐字打印的时候,还可以加入一些打字音效,这里我就不加了,留给大家自己补充

          源码

          https://gitcode.net/unity1/dialoguesystem

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第19张

          参考

          【视频】https://www.bilibili.com/video/BV1WJ411Y71J/

          完结

          赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

          好了,我是向宇,https://xiangyu.blog.csdn.net

          一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

          【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(20231226补充更新),在这里插入图片描述,第20张

网友评论

搜索
最新文章
热门文章
热门标签
 
 梦见别人给我洗头发是什么意思  梦见和人吵架什么意思  已婚女人梦见路上好多蛇