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++;
}
}
本篇完