01对话系统---文字渐出和停顿效果

实现代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System.Text.RegularExpressions;
using System;

/// <summary>
/// 增加文本时间停顿功能
/// 增加文字渐出,(单个字符逐渐显现)
/// </summary>



//文本时间停顿功能

//效果:如果使用AdvancedTextPreprocessor的预处理器
//则先经过string ITextPreprocessor.PreprocessText(string text)该方法处理的返回值
//才能显示出来

public class AdvancedTextPreprocessor : ITextPreprocessor
{
    //字典类型,表示在第几个字后面停顿的时间
    public Dictionary<int, float> InterrvalDictionary;

    public AdvancedTextPreprocessor()
    {
        InterrvalDictionary=new Dictionary<int, float>();
    }
    public string PreprocessText(string text)
    {
        //清空字典
        InterrvalDictionary.Clear();
        string processingText=text;
        //.:任意字符,*:匹配前面的字符零次或者多次,?:匹配最近的结果
        //*?匹配零次或者多次的那个最短的结果
        string pattern = "<.*?>";
        //输入的字符串+以那种规则去匹配的字符串
       Match match= Regex.Match(processingText,pattern);
       //删掉所有标签
        //如果可以匹配到结果
        while(match.Success)
        {
            string label = match.Value.Substring(1,match.Length - 2);
            //如果能转换为浮点类型则进入if,结果存到 result中
            if (float.TryParse(label,out float result))
            {
                //因为<0.3>前面还有<占一个位置
                InterrvalDictionary[match.Index - 1] = result;
            }
            //删掉标签
            processingText=processingText.Remove(match.Index,match.Length);
            match = Regex.Match(processingText,pattern);
        }
        //删掉数据标签
        processingText = text;
        //*     代表前一个字符出现零次或多次
        //+     代表前一个字符出现一次或多次
        //?     代表前一个字符出现零次或一次
        //.     代表任意字符
        pattern = @"<(\d+)(\.\d+)?>";
        //processingText中,把所有符合pattern规则的字符替换成"xxx"
        processingText = Regex.Replace(processingText, pattern, "");
        return processingText;
    }
}

public class AdvancedText : TextMeshProUGUI
{
    public AdvancedText()
    {
        //接口类型的预处理器textPreprocessor(可以自己定义预处理效果是什么样的)
        textPreprocessor = new AdvancedTextPreprocessor();
    }
    private AdvancedTextPreprocessor SelfPreprocessor => (AdvancedTextPreprocessor)textPreprocessor;
    public void ShowTextByTyping(string content)
    {
        SetText(content);
        StartCoroutine(Typing());
    }
    private int _typingIndex;
    private float _defaultInterval = 0.06f;

    IEnumerator Typing()
    {
        //强制网格更新
        ForceMeshUpdate();
        for (int i = 0; i < m_characterCount; i++)
        {
            //先把颜色设置成透明
            SetSingleCharacterAlpha(i, 0);
        }
        _typingIndex = 0;
        while (_typingIndex < m_characterCount)
        {
            if (textInfo.characterInfo[_typingIndex].isVisible)
            {
                StartCoroutine(FadeInCharacter(_typingIndex));
            }
            //SetSingleCharacterAlpha(_typingIndex, 255);           
            if (SelfPreprocessor.InterrvalDictionary.TryGetValue(_typingIndex, out float result))
            {
                yield return new WaitForSecondsRealtime(result);
            }
            else
            {
                yield return new WaitForSecondsRealtime(_defaultInterval);
            }
            _typingIndex++;
        }



        //yield return null;
    }
    //原理:改变单个文字的Alpha
    //newAlpha范围是0-255
    private void SetSingleCharacterAlpha(int index, byte newAlpha)
    {
        TMP_CharacterInfo charInfo = textInfo.characterInfo[index];
        //材质索引
        int matIndex = charInfo.materialReferenceIndex;
        //顶点索引
        int verIndex = charInfo.vertexIndex;
        for (int i = 0; i < 4; i++)
        {
            //color32表示所有的顶点颜色
            textInfo.meshInfo[matIndex].colors32[verIndex + i].a = newAlpha;
        }
        UpdateVertexData();
    }

    // 渐显角色函数,用于平滑地调整角色透明度
    IEnumerator FadeInCharacter(int index, float duration = 0.2f)
    {
        //瞬间显示
        if (duration <= 0)
        {
            SetSingleCharacterAlpha(index, 255);
        }
        else
        {
            float timer = 0;
            while(timer<duration)
            {
                //unscaledDeltaTime不考虑时间的放缩,游戏暂停的时候也不停止
                //timer不能超过duration
                timer = Mathf.Min(duration, timer + Time.unscaledDeltaTime);
                SetSingleCharacterAlpha(index, (byte)(255 * timer / duration));
                yield return null;
            }
        }
    }
}

测试用例(绑定在相机中即可)

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

public class Test : MonoBehaviour
{
    [SerializeField] private AdvancedText _text;
    //下面的字符串可以多行输入
    [Multiline]
    [SerializeField] private string content;
    // Start is called before the first frame update
    void Start() 
    {
        _text.ShowTextByTyping(content);
    }

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

代码绑定

把原来3D text组件的TextMshPro组件删除,把自己写的AdvancedText脚本绑定上去

标签

改变颜色

<color=#FF0000>New</color>Text

效果

加粗

<b>

截至:</b>

eg.<b>New</b>Text

斜体

<i>

截至:</i>

eg.<i>New</i>Text

字体大小

扩大到原来的1.5倍:size=150%

自建高级文本组件(停顿计时)

本质是重写TextMshPro组件,变成更高级的AdvancedText脚本

脚本名称:AdvancedText

创建位置:

导入using TMPro;

继承自TextMeshProUGUI

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

public class AdvancedText : TextMeshProUGUI
{
    
}

删除原来的TextMshPro组件

导入创建的脚本组件

补充

1.

//protected override void Start()是在继承关系中重写基类中的受保护方法
protected override void Start()
{
    base.Start();
    
}

2.

using TMPro;
//效果:如果使用AdvancedTextPreprocessor的预处理器
//则先经过string ITextPreprocessor.PreprocessText(string text)该方法处理的返回值
//才能显示出来

public class AdvancedTextPreprocessor : ITextPreprocessor
{
    public string PreprocessText(string text)
    {
        return "Eromouga";
    }
}

public class AdvancedText : TextMeshProUGUI
{
   public AdvancedText() 
    {
        //接口类型的预处理器textPreprocessor(可以自己定义预处理效果是什么样的)
        textPreprocessor = new AdvancedTextPreprocessor();
    }
    
    
}

 预处理器效果

3.

 string processingText=text;
 string patten="<.*?>"
 //输入的字符串+以那种规则去匹配的字符串
Match match= Regex.Match(processingText,patten);

.:任意字符,*:匹配前面的字符零次或者多次,?:匹配最近的结果
*?匹配零次或者多次的那个最短的结果

正则表达式(Regular Expression,通常简写为regex或regexp)是一种文本模式匹配的工具,它用于描述或匹配一系列符合某个句法规则的字符串。在编程和文本处理中,正则表达式被广泛用于搜索、替换和验证文本。

正则表达式由一系列字符和特殊符号组成,这些符号具有特定的含义,可以用来匹配字符串中的特定模式。以下是一些常见的正则表达式元字符和它们的含义:

  • .:匹配任意单个字符(除了换行符)。
  • ^:匹配字符串的开始。
  • $:匹配字符串的结束。
  • *:匹配前面的字符0次或多次。
  • +:匹配前面的字符1次或多次。
  • ?:匹配前面的字符0次或1次。
  • {n}:匹配前面的字符恰好n次。
  • {n,}:匹配前面的字符至少n次。
  • {n,m}:匹配前面的字符至少n次,但不超过m次。
  • []:定义一个字符集合,匹配集合中的任意一个字符。
  • ():定义一个捕获组。
  • |:表示或的关系,匹配两边的任意一个表达式。
  • \:转义字符,用于匹配特殊字符本身。

例如,正则表达式 a*b 可以匹配 "b", "ab", "aab", "aaab", 等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值