Bootstrap

构建互动叙事:在Unity中打造简易对话系统

获取素材、文字教程、视频教程等,关注微信公众号”90后小陈老师“回复”对话系统“

1.简介

对话系统在大量游戏都会出现,如何实现一个简易的对话系统呢?本教程将会逐步实现。
在这里插入图片描述

1.1 功能

  1. 对话面板由左侧说话人头像和右侧对话内容组成。
  2. 点击“D”键开始对话,显示对话面板。
  3. 点击“N”键显示下一句对话,对话会逐字输出,当前对话未输出完,再点击“N”键即可快速显示当前对话。
  4. 对话完成后,对话面板自动隐藏。

1.2 知识点

  1. UGUI:Unity游戏界面制作。
  2. TextAsset:文本资源。
  3. 协程:实现逐字输出。

2.UI制作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.素材导入

在这里插入图片描述

唐僧
悟空,为何停下脚步?
孙悟空
师父,前方有妖气!
唐僧
你如何知晓?
孙悟空
老孙火眼金睛,能看六百里。前方山坳有妖怪埋伏。
唐僧
那我们还是绕道而行吧。
孙悟空
不妨事,让老孙去教训他们一番。
唐僧
切记不可伤人性命!
孙悟空
放心吧师父,老孙只吓唬他们一下。
唐僧
你这猴头,只要懂得慈悲为怀就好...
孙悟空
弟子明白,定不会过分。

4.读取文档文件

新建脚本“DialoguePanel.cs”挂载到组件“DialoguePanel”面板上
获取组件、文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DialoguePanel : MonoBehaviour
{
    [Header("UI组件")]
    public Image faceImage;//头像图片
    public Text dialogueText;//对话文本

    [Header("文本文件相关")]
    public TextAsset textFile;//文本文件

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

输出文本

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DialoguePanel : MonoBehaviour
{
    [Header("UI组件")]
    public Image faceImage;//头像图片
    public Text dialogueText;//对话文本

    [Header("文本文件相关")]
    public TextAsset textFile;//文本文件

    int lineIndex;//文本行序号,默认为0
    string[] textLines;//文本行列表

    // Start is called before the first frame update
    void Start()
    {
        lineIndex = 0;

        LoadText();
        ShowText();
    }

    // Update is called once per frame
    void Update()
    {
        //点击N输出文本
        if (Input.GetKeyDown(KeyCode.N))
        {
            //超出长度索引归零,隐藏对话面板
            if (lineIndex >= textLines.Length)
            {
                lineIndex = 0;
                gameObject.SetActive(false);
                return;
            }

            ShowText();
        }
    }

    /// <summary>
    /// 载入文本
    /// </summary>
    void LoadText()
    {
        textLines = textFile.text.Split("\n");
    }

    /// <summary>
    /// 显示对话文本
    /// </summary>
    void ShowText()
    {
        dialogueText.text = textLines[lineIndex];
        lineIndex++;
    }
}

5.使用协程逐字输出

点击“N”键显示下一句对话,对话会逐字输出,当前对话未输出完,再点击“N”键即可快速显示当前对话。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DialoguePanel : MonoBehaviour
{
    [Header("UI组件")]
    public Image faceImage;//头像图片
    public Text dialogueText;//对话文本

    [Header("文本文件相关")]
    public TextAsset textFile;//文本文件

    int lineIndex;//文本行序号,默认为0
    string[] textLines;//文本行列表
    float textDelay;//逐字输出文本延时
    bool typeEnd;//逐字输出文本是否结束
    bool cancelType;//是否取消逐字输出

    // Start is called before the first frame update
    void Start()
    {
        lineIndex = 0;
        textDelay = 0.1f;
        typeEnd = true;
        cancelType = false;

        LoadText();
        StartCoroutine(ShowText());
    }

    // Update is called once per frame
    void Update()
    {
        //点击N输出文本
        if (Input.GetKeyDown(KeyCode.N))
        {
            //超出长度索引归零,隐藏对话面板
            if (lineIndex >= textLines.Length)
            {
                lineIndex = 0;
                gameObject.SetActive(false);
                return;
            }

            //对话输出完成后输出下一句
            if (typeEnd)
            {
                StartCoroutine(ShowText());
            }
            //对话输出未完成再次点击N则快速输出对话
            else
            {
                StopAllCoroutines();
                dialogueText.text = textLines[lineIndex];
                lineIndex++;
                typeEnd = true;
            }
        }
    }

    /// <summary>
    /// 载入文本
    /// </summary>
    void LoadText()
    {
        textLines = textFile.text.Split("\n");
    }

    /// <summary>
    /// 显示对话文本
    /// </summary>
    IEnumerator ShowText()
    {
        var line = textLines[lineIndex];
        dialogueText.text = "";
        typeEnd = false;

        //逐字延时一定时间输出
        foreach (var letter in line)
        {
            dialogueText.text += letter;
            yield return new WaitForSeconds(textDelay);
        }

        lineIndex++;
        typeEnd = true;
    }
}

6.显示头像

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DialoguePanel : MonoBehaviour
{
    [Header("UI组件")]
    public Image faceImage;//头像图片
    public Text dialogueText;//对话文本

    [Header("文本文件相关")]
    public TextAsset textFile;//文本文件

    [Header("头像")]
    public Sprite tangFace;
    public Sprite sunFace;

    int lineIndex;//文本行序号,默认为0
    string[] textLines;//文本行列表
    float textDelay;//逐字输出文本延时
    bool typeEnd;//逐字输出文本是否结束

    // Start is called before the first frame update
    void Start()
    {
        lineIndex = 0;
        textDelay = 0.1f;
        typeEnd = true;

        LoadText();
        StartCoroutine(ShowText());
    }

    // Update is called once per frame
    void Update()
    {
        //点击N输出文本
        if (Input.GetKeyDown(KeyCode.N))
        {
            //超出长度索引归零,隐藏对话面板
            if (lineIndex >= textLines.Length)
            {
                lineIndex = 0;
                gameObject.SetActive(false);
                return;
            }

            //对话输出完成后输出下一句
            if (typeEnd)
            {
                StartCoroutine(ShowText());
            }
            //对话输出未完成再次点击N则快速输出对话
            else
            {
                StopAllCoroutines();
                dialogueText.text = textLines[lineIndex];
                lineIndex++;
                typeEnd = true;
            }
        }
    }

    /// <summary>
    /// 载入文本
    /// </summary>
    void LoadText()
    {
        textLines = textFile.text.Split("\n");
    }

    /// <summary>
    /// 显示对话文本
    /// </summary>
    IEnumerator ShowText()
    {
        //显示头像
        switch (textLines[lineIndex])
        {
            case "唐僧\r":
                faceImage.sprite = tangFace;
                lineIndex++;
                break;
            case "孙悟空\r":
                faceImage.sprite = sunFace;
                lineIndex++;
                break;
        }

        var line = textLines[lineIndex];
        dialogueText.text = "";
        typeEnd = false;

        //逐字延时一定时间输出
        foreach (var letter in line)
        {
            dialogueText.text += letter;
            yield return new WaitForSeconds(textDelay);
        }

        lineIndex++;
        typeEnd = true;
    }
}

7.显示对话面板

设置隐藏对话面板

Canva挂载新建的脚本GameManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public GameObject dialoguePanel;//对话面板

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //如果对话面板未显示,按下D键则显示对话面板
        if(!dialoguePanel.activeSelf && Input.GetKeyDown(KeyCode.D))
        {
            dialoguePanel.SetActive(true);
        }
    }
}

获取素材、文字教程、视频教程等,关注微信公众号”90后小陈老师“回复”对话系统“

;