当前位置: 首页 > article >正文

Unity功能模块一对话系统(2)打字机淡入效果

本期我们先来实现简单常见的打字机及文本淡入的动画效果。

一.实现文本透明度修改

我们先来实现文本透明度的修改的功能

基本思路

遍历textinfo中的数组characterinfo,修改其中character成员的网格顶点的透明度。

实现源码

using System.Collections;
using TMPro;

public class AdvancedText : TextMeshProUGUI
{

    public void ShowText(string content)
    {
        SetText(content);
        StartCoroutine(Typing());
    }

    IEnumerator Typing()
    {
        ForceMeshUpdate();
        for (int i = 0; i < m_characterCount; i++)
        {
            SetSingleCharacterAlpha(i, 20);
        }
        yield return null;
    }


    /// <summary>
    /// 设置单个字符的透明度(每个字符都是由网格(含4个顶点)渲染)
    /// </summary>
    /// <param name="index"></param>
    /// <param name="newAlpha">newalpha范围为0~255</param>
    void SetSingleCharacterAlpha(int index, byte newAlpha)
    {
        TMP_CharacterInfo character = textInfo.characterInfo[index];//获取文本内容索引下的单个字符
        int matIndex = character.materialReferenceIndex;//获取字符材质索引
        int vertexIndex = character.vertexIndex;//获取字符顶点索引
        for (int i = 0; i < 3; i++)
        {
            textInfo.meshInfo[matIndex].colors32[vertexIndex + i].a = newAlpha;
        }
        UpdateVertexData();//更新顶点数据
    }
}

测试脚本

创建测试脚本TMPTest,编辑器内配置我们的TMP组件和文本内容

using UnityEngine;

public class TMPTest : MonoBehaviour
{
    public AdvancedText Atext;
    [TextArea]
    public string content;
    private void Start()
    {
        Atext.ShowText(content);
    }
}

运行效果

(注意我在代码中只修改了character的三个顶点的透明度,所以出现上图的效果)

可以发现,每个文本字符其实都是由4个顶点所构成的mesh网格,且顶点顺序为左下角为索引0,顺时针排布的形式。

当然,我们也是可以应用上富文本实现一些简单的效果。


二.实现打字机效果

接着我们实现打字机的效果。

基本思路

初始文本整体修改透明度为0,当触发对话时,再逐个改变字符的透明度。

我们简单修改一下Typing这个携程即可实现。

实现源码

public class AdvancedText : TextMeshProUGUI
{
    int typingIndex;
    float defalutInterval=0.5f;
    public void ShowText(string content)
    {
        SetText(content);
        StartCoroutine(Typing());
    }

    IEnumerator Typing()
    {
        ForceMeshUpdate();
        //将文本透明度修改为0,通过携程逐个修改字符的透明度
        for (int i = 0; i < m_characterCount; i++)
        {
            SetSingleCharacterAlpha(i, 0);
        }
        typingIndex = 0;
        while (typingIndex<m_characterCount) 
        {
            SetSingleCharacterAlpha(typingIndex,255);
            yield return  new WaitForSecondsRealtime(defalutInterval);
            typingIndex++;
        }
    }


    /// <summary>
    /// 设置单个字符的透明度(每个字符都是由网格(含4个顶点)渲染)
    /// </summary>
    /// <param name="index"></param>
    /// <param name="newAlpha">newalpha范围为0~255</param>
    void SetSingleCharacterAlpha(int index, byte newAlpha)
    {
        TMP_CharacterInfo character = textInfo.characterInfo[index];//获取文本内容索引下的单个字符
        int matIndex = character.materialReferenceIndex;//获取字符材质索引
        int vertexIndex = character.vertexIndex;//获取字符顶点索引
        for (int i = 0; i < 4; i++)
        {
            textInfo.meshInfo[matIndex].colors32[vertexIndex + i].a = newAlpha;
        }
        UpdateVertexData();//更新顶点数据
    }
}

运行效果


三.实现打字机淡入效果

非常好,我们已经实现了简单的打字机效果,接着我们实现一下打字机淡入效果。

基本思路

在打字机设置单字符显示时,采用携程实现透明度递增的效果。

实现源码

using System.Collections;
using TMPro;
using UnityEngine;

public class AdvancedText : TextMeshProUGUI
{
    int typingIndex;
    float defalutInterval=0.5f;
    public void ShowText(string content)
    {
        SetText(content);
        StartCoroutine(Typing());
    }

    IEnumerator Typing()
    {
        ForceMeshUpdate();
        for (int i = 0; i < m_characterCount; i++)
        {
            SetSingleCharacterAlpha(i, 0);
        }
        typingIndex = 0;
        while (typingIndex<m_characterCount) 
        {
            //SetSingleCharacterAlpha(typingIndex,255);   //无淡入打字机效果
            StartCoroutine(FadeInCharacter(typingIndex)); //淡入打字机效果
            yield return  new WaitForSecondsRealtime(defalutInterval);
            typingIndex++;
        }
    }


    /// <summary>
    /// 设置单字符的透明度(每个字符都是由网格(含4个顶点)渲染)
    /// </summary>
    /// <param name="index"></param>
    /// <param name="newAlpha">newalpha范围为0~255</param>
    void SetSingleCharacterAlpha(int index, byte newAlpha)
    {
        TMP_CharacterInfo character = textInfo.characterInfo[index];//获取文本内容索引下的单个字符
        int matIndex = character.materialReferenceIndex;//获取字符材质索引
        int vertexIndex = character.vertexIndex;//获取字符顶点索引
        for (int i = 0; i < 4; i++)
        {
            textInfo.meshInfo[matIndex].colors32[vertexIndex + i].a = newAlpha;
        }
        UpdateVertexData();//更新顶点数据
    }

    /// <summary>
    /// 单字符淡入
    /// </summary>
    /// <param name="index"></param>
    /// <param name="duration"></param>
    /// <returns></returns>
    IEnumerator FadeInCharacter(int index,float duration=1f) 
    {
        if (duration <= 0)  
           SetSingleCharacterAlpha(index,255);
        else 
        {
            float timer = 0;
            while (timer < duration) 
            {
                timer=Mathf.Min(duration, timer+Time.unscaledDeltaTime);
                SetSingleCharacterAlpha(index, (byte) (255 * (timer / duration)));
                yield return null;
            }
        }
    }
}

运行效果

现在我们实现了打字机和淡入打字机的动画效果。效果很不错!

潜在Bug处理

当我们的文本不存在空格等不可见字符时,动画效果是正确的,但当我们的文本含有此类不可见字符时,会出现下面这种异常现象。

我在”每天”后留了3个空格

异常运行结果如下图:

可能是在文本的目标索引上没有找到可以设置透明度的可见字符,所以就去找了第一个可见字符,“每”在读取空格位时变化了3次。

所以我们需要在开启字符淡入携程前要判断目标读取位置是否为可见字符

修改后的Typing()携程函数如下:

 IEnumerator Typing()
 {
     ForceMeshUpdate();
     for (int i = 0; i < m_characterCount; i++)
     {
         SetSingleCharacterAlpha(i, 0);
     }
     typingIndex = 0;
     while (typingIndex < m_characterCount)
     {
         //SetSingleCharacterAlpha(typingIndex,255);   //无淡入打字机效果
         if (textInfo.characterInfo[typingIndex].isVisible)
         {
             StartCoroutine(FadeInCharacter(typingIndex)); //淡入打字机效果
         }
         yield return new WaitForSecondsRealtime(defalutInterval);
         typingIndex++;
     }
 }

本篇完


http://www.kler.cn/a/457129.html

相关文章:

  • 2024165读书笔记|《飞花令·合》——人生飘忽百年内,且须酣畅万古情
  • Java开发工具-Jar命令
  • 最小特权的例子
  • 分区表全局索引split测试
  • GraphRAG 框架哪家强?选择最适合你智能问答系统的框架
  • c# 线程 AutoResetEvent 的Set()函数多次调用
  • 喜报 | 擎创科技入围上海市优秀信创解决方案
  • Rancher V2.9.0 Docker安装教程
  • 神经网络入门实战:(二十二)只训练 (多层网络的) 指定层 / (单层网络的) 指定参数
  • 青少年编程与数学 02-005 移动Web编程基础 06课题、响应式设计
  • Web 漏洞之 CSRF 漏洞挖掘:攻防深度剖析
  • SelectionArea 实现富文本
  • 【源码 导入教程 文档 讲解】基于springboot校园新闻管理系统源码和论文
  • 【13】MySQL如何选择合适的索引?
  • 【GlobalMapper精品教程】091:根据指定字段融合图斑(字段值相同融合到一起)
  • C++学习指南
  • 初识MySQL · 库的操作
  • linux内核系列---网络
  • Java圣诞树
  • 数据结构:二叉树部分接口(链式)
  • 力扣算法--求两数之和等于目标数
  • MySQL的TIMESTAMP类型字段非空和默认值属性的影响
  • 用科技的方法能否实现真正的智能
  • DAY3 QT简易登陆界面优化
  • blender中合并的模型,在threejs中显示多个mesh;blender多材质烘培成一个材质
  • Debian 12 安装配置 fail2ban 保护 SSH 访问