实现代码
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", 等等。