Unity—对话系统&&GalGame游戏文字对话制作

每日一句:人间总有一两,填我十万八千梦

目录

对话系统

文本逐字打印功能

GalGame游戏(美少女游戏)文字对话


对话系统

被触发物体(挂载脚本)下UI,先不激活

public class TalkButton : MonoBehaviour

{

    public GameObject tipshow;//提示UI

    public GameObject talkUI;//对话UI

    private void OnTriggerEnter(Collider other)

    {

        Debug.Log("aaa");

        tipshow.SetActive(true);

    }

    private void OnTriggerExit(Collider other)

    {

        tipshow.SetActive(false);

    }

private void Update()

    {

        if(tipshow.activeSelf&&Input.GetKeyDown(KeyCode.R))

        {

            talkUI.SetActive(true);

        }

    }

}

TextAsset文档文件

 

 

(用记事本另存为txt文本文件,导入Unity中)

DialogSystem类

public class DialogSystem : MonoBehaviour

{

    public Text textLabel;//文字组件

    public Image faceImage;//头像图片

    public TextAsset textFile;

    public int index;//文本内容索引+

    public Sprite face01, face02;

    public float textSpeed;

    bool textFinished;//判断是否输出完了当前行的内容

    List<string> textList = new List<string>();

    bool cancelTyping;//取消逐字打印

    private void Awake()

    {

        GetTextFormFile(textFile);//从文本文件中得到文本内容

    }

    private void OnEnable()

    {

        textFinished = true;//当前文本没有输出完

        StartCoroutine(SetTextUI());//获得这一行长度的每一个文字,累加输出

    }

    private void Update()

    {

        if(Input.GetKeyDown(KeyCode.R)&&index==textList.Count)//如果按下R键,并且当前文本索引等于文本总长度

        {

            gameObject.SetActive(false);//销毁当前对话框

            index = 0;//索引归零

            return;

        }

        if (Input.GetKeyDown(KeyCode.R))//按下R键

        {

            if (textFinished && !cancelTyping)//如果上一行文本输入完,并没有取消逐字打印

            {

                StartCoroutine(SetTextUI());//开启逐字打印

            }

            else if (!textFinished && !cancelTyping)//如果上一行文本没有输入完,并没有取消逐字打印

            {

                cancelTyping = true;//取消逐字打印

            }

        }

    }

    /// <summary>

    /// 把整片文件分成每一行,输出到一个列表中,再转换成文本

    /// </summary>

    /// <param name="file"></param>

    void GetTextFormFile(TextAsset file)

    {

        textList.Clear();

        index = 0;

        var lineData = file.text.Split("\n");

        foreach(var line in lineData)

        {

            textList.Add(line);

        }

    }

    /// <summary>

    /// 获得这一行长度的每一个文字,累加输出

    /// </summary>

    /// <returns></returns>

    IEnumerator SetTextUI()

    {

        textLabel.text = "";

        textFinished = false;//文本内容正在输出

        switch (textList[index].Trim().ToString())

        {

            case "A":

                faceImage.sprite = face01;

                Debug.Log("aaa");

                index++;

                break;

            case "B":

                faceImage.sprite = face02;

                index++;

                Debug.Log("bbb");

                break;

        }

        int letter = 0;

        while(!cancelTyping&&letter<textList[index].Length-1)

        {

            Debug.Log("逐字打印");

            textLabel.text += textList[index][letter];

            letter++;

            yield return new WaitForSeconds(textSpeed);

        }

        cancelTyping = false;

        textFinished = true;

        index++;

    }

}

文本逐字打印功能

public class TypewriterEffect : MonoBehaviour

{

    public float charsPerSecond = 0.2f;//打字时间间隔

    private string words;//保存需要显示的文字

    private bool isActive = false;

    private float timer;//计时器

    private Text myText;

    private int currentPos = 0;//当前打字位置

    // Use this for initialization

    void Start()

    {

        timer = 0;

        isActive = true;

        charsPerSecond = Mathf.Max(0.2f, charsPerSecond);

        myText = GetComponent<Text>();

        words = myText.text;

        myText.text = "";//获取Text的文本信息,保存到words中,然后动态更新文本显示内容,实现打字机的效果

    }

    // Update is called once per frame

    void Update()

    {

        OnStartWriter();

    }

    /// <summary>

    /// 执行打字任务

    /// </summary>

    void OnStartWriter()

    {

        if (isActive)

        {

            timer += Time.deltaTime;

            if (timer >= charsPerSecond)

            {//判断计时器时间是否到达

                timer = 0;

                currentPos++;

                myText.text = words.Substring(0, currentPos);//刷新文本显示内容

                if (currentPos >= words.Length)

                {

                    OnFinish();

                }

            }

        }

    }

    /// <summary>

    /// 结束打字,初始化数据

    /// </summary>

    void OnFinish()

    {

        isActive = false;

        timer = 0;

        currentPos = 0;

        myText.text = words;

    }

}

substring()的作用就是截取父字符串的某一部分

public String substring(int beginIndex, int endIndex)

第一个参数int为开始的索引,对应String数字中的开始位置,

第二个参数是截止的索引位置,对应String中的结束位置

GalGame游戏(美少女游戏)文字对话

Galgame游戏

剧本数据类

public class GameManager_BE : MonoBehaviour

{

    public static GameManager_BE Instance { get; private set; }//单例模式

    private List<ScriptData_BE> scriptDatas_BE;

    private int scriptIndex;

private void Awake()

    {

        Instance = this;

        scriptDatas_BE = new List<ScriptData_BE>()

        { //编写剧本对话

            new ScriptData_BE()

            {

                loadType=1,BGspriteName="bg1"//背景图片名字路径

            },

            new ScriptData_BE()

            {

                loadType=2,dialogueContent="上古时期,魔神出世,颠覆六界,屠戮生灵"

            },

             new ScriptData_BE()

            {

                loadType=2,dialogueContent="诸天神尊牺牲毕生修为,献祭无上神器,才得以斩杀魔神。"

            },

              new ScriptData_BE()

            {

                loadType=2,dialogueContent="那一战,众神陨落,神器破碎,换来了,世间万年安宁。"

            },  

            new ScriptData_BE()

            {

                loadType=1,BGspriteName="bg2"//背景图片名字路径

            },

               new ScriptData_BE()

            {

                loadType=2,dialogueContent="然而万年后,第二位魔神横空出世,"

               

            },

                  new ScriptData_BE()

            {

                loadType=2,dialogueContent="他残忍嗜血,暴虐无道,比上古魔神更甚。"

            },

            new ScriptData_BE()

            {

                loadType=2,dialogueContent="各仙门拼死抵抗,修道者前赴后继。"

            },

            new ScriptData_BE()

            {

                loadType=2,dialogueContent="但,尘世已无神。"

            },

             new ScriptData_BE()

            {

                loadType=1,BGspriteName="bg4"//背景图片名字路径

            },

            new ScriptData_BE()

            {

                loadType=3,name="衡阳宗宗主",dialogueContent="自古魔王能号令天下魔物,因其天生邪骨,超脱六界。"

            },

            new ScriptData_BE()

            {

                loadType=3,name="衡阳宗宗主",dialogueContent="过去镜指出,五百年前的魔王,原身是个凡人,叫澹台烬。"

            },

             new ScriptData_BE()

            {

                loadType=3,name="衡阳宗宗主",dialogueContent="苏苏,今日子时是最佳时辰"

            },

              new ScriptData_BE()

            {

                loadType=3,name="衡阳宗宗主",dialogueContent="众位长老会用毕生修为,送你回到五百年前。"

            },

               new ScriptData_BE()

            {

                loadType=3,name="衡阳宗宗主",dialogueContent="那时的魔王还是凡人,你要抽出他邪骨,阻止他觉醒。"

            },

                new ScriptData_BE()

            {

                loadType=3,name="衡阳宗宗主",dialogueContent="想要拯救苍生,只有这个办法"

            },

                    new ScriptData_BE()

            {

                loadType=3,name="黎苏苏",dialogueContent="爹爹放心,苏苏一定全力以赴"

            },

                      new ScriptData_BE()

            {

                loadType=3,name="公治寂无",dialogueContent="师父,师妹年纪还小,让我代她吧"

            },

        };

        scriptIndex = 0;

        HandleData();

    }

    /// <summary>

    /// 处理每一条剧情数据

    /// </summary>

    private void HandleData()

    {

        if (scriptIndex >= scriptDatas_BE.Count)

        {

            Debug.Log("游戏结束");

            return;

        }

        

        if (scriptDatas_BE[scriptIndex].loadType == 1)

        {

            //设置一下背景图片

            SetBGImageSprite(scriptDatas_BE[scriptIndex].BGspriteName);

            //加载下一条剧情数据

            LoadNextScript();

        }

        if (scriptDatas_BE[scriptIndex].loadType == 2)//旁白对话

        {

            

            //更新对话框文本

            UpdateTalkLineText(scriptDatas_BE[scriptIndex].dialogueContent);

        }

        if (scriptDatas_BE[scriptIndex].loadType == 3)//人物对话

        {

            

            //显示人物

            ShowCharacter(scriptDatas_BE[scriptIndex].name);

            //更新对话框文本

            UpdateTalkLineText(scriptDatas_BE[scriptIndex].dialogueContent);

        }

    }

    //设置一下背景图片

    private void SetBGImageSprite(string spriteName)

    {

        UIManager_BE.Instance.SetBGImageSprite(spriteName);

    }

    //加载下一条剧情数据

    public void LoadNextScript()

    {

        Debug.Log("加载下一条剧情");

        scriptIndex++;

        HandleData();

    }

    //显示人物

    private void ShowCharacter(string name)

    {

        UIManager_BE.Instance.ShowCharacter(name);

    }

    //更新对话框文本

    private void UpdateTalkLineText(string dialogueContent)

    {

        UIManager_BE.Instance.UpdateTalkLineText(dialogueContent);

    }

}

/// <summary>

/// 剧本数据

/// </summary>

public class ScriptData_BE

{

    public int loadType;//载入资源类型 1.更换背景 2.旁白对话

    public string name;//角色名称

    public string BGspriteName;//图片资源路径

    public string dialogueContent;//对话内容

}

UIManager_BE

public class UIManager_BE : MonoBehaviour

{

    public static UIManager_BE Instance { get; private set; }

    public Image imgBG;//背景图片组件

    public Image imgCharacter;//人物图片组件

    public Text textName;//人物名称文字组件

    public Text textTalkLine;//人物对话文字组件

    public GameObject talkLineGo;//对话框父对象游戏物体

    private void Awake()

    {

        Instance = this;

    }

    /// <summary>

    /// 设置背景图片

    /// </summary>

    /// <param name="spriteName"></param>

    public void SetBGImageSprite(string spriteName)

    {

        imgBG.sprite = Resources.Load<Sprite>("Sprite_BE/" + spriteName);

    }

    /// <summary>

    /// 显示人物

    /// </summary>

    /// <param name="name"></param>

    public void ShowCharacter(string name)

    {

        talkLineGo.SetActive(true);

        imgCharacter.sprite = Resources.Load<Sprite>("Sprite_BE/" + name);

        imgCharacter.gameObject.SetActive(true);

        textName.text = name;

    }

    /// <summary>

    /// 更新对话内容

    /// </summary>

    /// <param name="dialogueContent"></param>

    public void UpdateTalkLineText(string dialogueContent)

    {

        textTalkLine.text = dialogueContent;

    }

}

 

通过按钮点击对话框,推动人物进行

【仅当学习笔记,特别感谢:M_Studio 我是Trigger呀 UP主,】

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity对话系统是一个轻量级的对话系统和界面,设计用于绑定到任何UI系统。它需要Unity 5.0.0或更高版本。 在Unity中实现对话系统的一种方法是使用VIDE Dialogues (Pro) 2.1。你需要在脚本中引入命名空间using UnityEngine.UI;,并创建相应的游戏对象和文本组件来显示对话内容。你可以使用[TextArea(1,3)]特性来在Inspector窗口中将文字区域显示为三行。对话内容可以存储在一个字符串数组中,并通过索引进行访问。你还可以将对话信息存储在ScriptableObject(SO)中,使用[CreateAssetMenu(fileName ="New Dialogue",menuName ="Dialogue/Dialogue Data")]特性来创建对话数据的菜单选项。对话数据可以存储在一个包含对话片段的列表中。 总之,Unity对话系统是一个可以绑定到任何UI系统的轻量级对话系统,可以通过使用VIDE Dialogues来实现,并且还可以使用ScriptableObject来存储对话数据。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Unity对话系统源码](https://download.csdn.net/download/nippyli/10143335)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [UNITY 对话系统](https://blog.csdn.net/qq_45783556/article/details/116171371)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Unity3D RPG实现 3 —— 对话、任务系统](https://blog.csdn.net/weixin_43757333/article/details/123287146)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值