【Unity3D小功能】Unity3D中UGUI-Text实现打字机效果

推荐阅读

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

需求要实现Text的打字机效果,一看居然还没这类型的教程,遂补上。

二、实现

2-1、使用DOTween插件实现效果

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class TextWriterDoTween : MonoBehaviour
{
    private void Start()
    {
        DoTweenText("123456", 6, () => 
        {
            Debug.Log("用6秒显示6个字");
        });
    }
    /// <summary>
    /// 打字机效果显示文字
    /// </summary>
    /// <param name="text">文字内容</param>
    /// <param name="time">时间</param>
    /// <param name="action">结束后执行方法</param>
    void DoTweenText(string text, float time, UnityAction action)
    {
        Text tmpText = transform.GetComponent<Text>();
        tmpText.text = string.Empty;
        try
        {
            tmpText.DOText(text, time, true, ScrambleMode.None, null).SetEase(Ease.Linear).OnComplete(() => { action(); });
        }
        catch (System.NullReferenceException)
        {
            Debug.LogError("该对象不存在Text组件");
        }
    }
}

效果图:
在这里插入图片描述

2-2、实现Text的打字机效果

参考代码:

using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

/// <summary>
/// 用于Text的打字机效果组件。
/// </summary>
[RequireComponent(typeof(Text))]
public class TextWriter : MonoBehaviour
{
    /// <summary>
    /// 打字机效果状态。
    /// </summary>
    public enum TypewriterState
    {
        /// <summary>
        /// 已完成输出。
        /// </summary>
        Completed,

        /// <summary>
        /// 正在输出。
        /// </summary>
        Outputting,

        /// <summary>
        /// 输出被中断。
        /// </summary>
        Interrupted
    }
    /// <summary>
    /// 打字机效果用时
    /// </summary>
    private float useTime;

    /// <summary>
    /// 打字机效果状态。
    /// </summary>
    private TypewriterState state = TypewriterState.Completed;

    /// <summary>
    /// Text组件。
    /// </summary>
    private Text tmpText;

    /// <summary>
    /// 文本内容。
    /// </summary>
    string words;

    /// <summary>
    /// 显示间隔。
    /// </summary>
    int charsSecond;

    /// <summary>
    /// 用于输出字符的协程。
    /// </summary>
    private Coroutine outputCoroutine;

    /// <summary>
    /// 字符输出结束时的回调。
    /// </summary>
    private UnityAction outputEndCallback;


    void Awake()
    {
        tmpText = GetComponent<Text>();
    }

    private void Start()
    {
        OutputText("123456", 12, () => {

            Debug.Log("用12秒显示6个字");
        });
    }

    void OnDisable()
    {
        // 中断输出
        if (state == TypewriterState.Outputting)
        {
            state = TypewriterState.Interrupted;
            StopCoroutine(outputCoroutine);
            OnOutputEnd(true);
        }
    }

    /// <summary>
    /// 输出文字。
    /// </summary>
    /// <param name="text"></param>
    /// <param name="onOutputEnd"></param>
    public void OutputText(string text, float time, UnityAction onOutputEnd = null)
    {
        // 如果当前正在执行字符输出,将其中断
        if (state == TypewriterState.Outputting)
        {
            StopCoroutine(outputCoroutine);

            state = TypewriterState.Interrupted;
            OnOutputEnd(false);
        }

        tmpText.text = text;
        useTime = time;
        outputEndCallback = onOutputEnd;
        words = text;

        // 如果对象未激活,直接完成输出
        if (!isActiveAndEnabled)
        {
            state = TypewriterState.Completed;
            OnOutputEnd(true);
            return;
        }
        outputCoroutine = StartCoroutine(OutputText());
    }

    /// <summary>
    /// 以不带淡入效果输出字符的协程。
    /// </summary>
    /// <param name="skipFirstCharacter"></param>
    /// <returns></returns>
    private IEnumerator OutputText()
    {
        state = TypewriterState.Outputting;

        // 先隐藏所有字符
        tmpText.text = "";

        // 按时间逐个显示字符
        float timer = 0f;
        Text textInfo = tmpText;
        float speed = useTime / words.Length;//计算出出现文字的间隔
        while (charsSecond < words.Length)
        {
            timer += Time.deltaTime;
            if (timer >= speed)
            {
                timer = 0;
                charsSecond++;
                tmpText.text = words.Substring(0, charsSecond);
            }
            yield return null;
        }

        // 输出过程结束
        state = TypewriterState.Completed;
        OnOutputEnd(false);
    }

    /// <summary>
    /// 完成正在进行的打字机效果,将所有文字显示出来。
    /// </summary>
    public void CompleteOutput()
    {
        if (state == TypewriterState.Outputting)
        {
            state = TypewriterState.Completed;
            StopCoroutine(outputCoroutine);
            OnOutputEnd(true);
        }
    }

    /// <summary>
    /// 处理输出结束逻辑。
    /// </summary>
    /// <param name="isShowAllCharacters"></param>
    private void OnOutputEnd(bool isShowAllCharacters)
    {
        // 清理协程
        outputCoroutine = null;

        // 将所有字符显示出来
        if (isShowAllCharacters)
        {
            tmpText.text = words;
        }

        // 触发输出完成回调
        if (outputEndCallback != null)
        {
            var temp = outputEndCallback;
            outputEndCallback = null;
            temp.Invoke();
        }
    }
}

效果图:
在这里插入图片描述

2-3、使用TextMeshPro实现打字机效果

参考代码:

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

namespace Tools
{
    /// <summary>
    /// 打字机效果状态。
    /// </summary>
    public enum TypewriterState
    {
        /// <summary>
        /// 已完成输出。
        /// </summary>
        Completed,

        /// <summary>
        /// 正在输出。
        /// </summary>
        Outputting,

        /// <summary>
        /// 输出被中断。
        /// </summary>
        Interrupted
    }
    /// <summary>
    /// 用于TextMeshPro的打字机效果组件。
    /// </summary>
    [RequireComponent(typeof(TextMeshProUGUI))]
    public class TextWriterTmp : MonoBehaviour
    {
        /// <summary>
        /// 打字机效果用时
        /// </summary>
        private float useTime;

        /// <summary>
        /// 打字机效果状态。
        /// </summary>
        private TypewriterState state = TypewriterState.Completed;

        /// <summary>
        /// TextMeshPro组件。
        /// </summary>
        private TMP_Text tmpText;

        /// <summary>
        /// 用于输出字符的协程。
        /// </summary>
        private Coroutine outputCoroutine;

        /// <summary>
        /// 字符输出结束时的回调。
        /// </summary>
        private UnityAction outputEndCallback;

        /// <summary>
        /// 输出文字。
        /// </summary>
        /// <param name="text"></param>
        /// <param name="onOutputEnd"></param>
        public void OutputText(string text, float time, UnityAction onOutputEnd = null)
        {
            // 如果当前正在执行字符输出,将其中断
            if (state == TypewriterState.Outputting)
            {
                StopCoroutine(outputCoroutine);

                state = TypewriterState.Interrupted;
                OnOutputEnd(false);
            }

            tmpText.text = text;
            useTime = time;
            outputEndCallback = onOutputEnd;

            // 如果对象未激活,直接完成输出
            if (!isActiveAndEnabled)
            {
                state = TypewriterState.Completed;
                OnOutputEnd(true);
                return;
            }
            outputCoroutine = StartCoroutine(OutputText());

        }

        /// <summary>
        /// 完成正在进行的打字机效果,将所有文字显示出来。
        /// </summary>
        public void CompleteOutput()
        {
            if (state == TypewriterState.Outputting)
            {
                state = TypewriterState.Completed;
                StopCoroutine(outputCoroutine);
                OnOutputEnd(true);
            }
        }

        private void Awake()
        {
            tmpText = GetComponent<TMP_Text>();
        }

        private void Start()
        {
            OutputText("123456", 6, () => 
            {
                Debug.Log("用6秒显示6个字");
            });
        }

        private void OnDisable()
        {
            // 中断输出
            if (state == TypewriterState.Outputting)
            {
                state = TypewriterState.Interrupted;
                StopCoroutine(outputCoroutine);
                OnOutputEnd(true);
            }
        }

        /// <summary>
        /// 以不带淡入效果输出字符的协程。
        /// </summary>
        /// <param name="skipFirstCharacter"></param>
        /// <returns></returns>
        private IEnumerator OutputText(bool skipFirstCharacter = false)
        {
            state = TypewriterState.Outputting;

            // 先隐藏所有字符
            tmpText.maxVisibleCharacters = skipFirstCharacter ? 1 : 0;
            tmpText.ForceMeshUpdate();

            // 按时间逐个显示字符
            float timer = 0f;
            TMP_TextInfo textInfo = tmpText.textInfo;
            float speed = useTime / textInfo.characterCount;
            while (tmpText.maxVisibleCharacters < textInfo.characterCount)
            {
                timer += Time.deltaTime;
                if (timer >= speed)
                {
                    timer = 0;
                    tmpText.maxVisibleCharacters++;
                }
                yield return null;
            }

            // 输出过程结束
            state = TypewriterState.Completed;
            OnOutputEnd(false);
        }



        /// <summary>
        /// 设置字符的顶点颜色Alpha值。
        /// </summary>
        /// <param name="index"></param>
        /// <param name="alpha"></param>
        private void SetCharacterAlpha(int index, byte alpha)
        {
            var materialIndex = tmpText.textInfo.characterInfo[index].materialReferenceIndex;
            var vertexColors = tmpText.textInfo.meshInfo[materialIndex].colors32;
            var vertexIndex = tmpText.textInfo.characterInfo[index].vertexIndex;

            vertexColors[vertexIndex + 0].a = alpha;
            vertexColors[vertexIndex + 1].a = alpha;
            vertexColors[vertexIndex + 2].a = alpha;
            vertexColors[vertexIndex + 3].a = alpha;
        }

        /// <summary>
        /// 处理输出结束逻辑。
        /// </summary>
        /// <param name="isShowAllCharacters"></param>
        private void OnOutputEnd(bool isShowAllCharacters)
        {
            // 清理协程
            outputCoroutine = null;

            // 将所有字符显示出来
            if (isShowAllCharacters)
            {
                var textInfo = tmpText.textInfo;
                for (int i = 0; i < textInfo.characterCount; i++)
                {
                    SetCharacterAlpha(i, 255);
                }

                tmpText.maxVisibleCharacters = textInfo.characterCount;
                tmpText.ForceMeshUpdate();
            }

            // 触发输出完成回调
            if (outputEndCallback != null)
            {
                var temp = outputEndCallback;
                outputEndCallback = null;
                temp.Invoke();
            }
        }
    }
}

效果图:
在这里插入图片描述

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏 方向 简介
Unity3D开发小游戏 小游戏开发教程 分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶 入门 从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUI UGUI Unity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据 文件读取 使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合 数据集合 数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发 虚拟仿真 总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件 插件 主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发 日常记录 主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG 日常记录 记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

相关推荐

  1. Unity3D UGUI适配不同分辨率详解

    2024-06-07 20:40:03       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-07 20:40:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-07 20:40:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-07 20:40:03       82 阅读
  4. Python语言-面向对象

    2024-06-07 20:40:03       91 阅读

热门阅读

  1. 蓝桥杯嵌入式学习

    2024-06-07 20:40:03       25 阅读
  2. 力扣2379.得到k个黑块的最少涂色次数

    2024-06-07 20:40:03       26 阅读
  3. Linux安装Nginx、配置SSL

    2024-06-07 20:40:03       21 阅读
  4. 模式识别选择题

    2024-06-07 20:40:03       25 阅读
  5. 【MATLAB高级编程】入门篇 | 向量化编程

    2024-06-07 20:40:03       24 阅读
  6. 关于学习flutter笔记

    2024-06-07 20:40:03       33 阅读
  7. Netty网络应用框架

    2024-06-07 20:40:03       23 阅读
  8. 【QT】QFont字体设置

    2024-06-07 20:40:03       24 阅读
  9. Mac电脑重置网络命令

    2024-06-07 20:40:03       26 阅读