针对第一版的优化,自动适配文字大小,TextMeshPro可以拓展各种语言。第一版字母类语言效果更好。
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public partial class TextBeatCom
{
List<RectTransform> m_showList = new List<RectTransform>();
List<Animator> m_aniList = new List<Animator>();
string m_text = string.Empty;
int m_space = 50;
float m_textSize = 1;
public void Init(string text, int space = 50)
{
if (string.IsNullOrEmpty(text)) return;
m_text = text;
m_space = space;
m_textSize = 1;
ResetContent();
ShowText();
}
void ShowText()
{
CreateTextItem();
StartCoroutine(PlayAnimation());
}
void CreateTextItem()
{
float last = 0, move = 0, textLength = 0;
int length = m_text.Length;
for (int index = 0; index < length; index++)
{
var sChar = m_text[index].ToString();
if (sChar != " ")//排除空格
{
float sx = 80;
var obj = InstantiateChild(sChar, out sx);
if (obj != null)
{
textLength += sx;
var rt = obj.GetComponent<RectTransform>();
m_showList.Add(rt);
}
}
else
{
textLength += m_space;
m_showList.Add(null);
}
}
m_textSize = (float)Screen.width / textLength;
m_textSize = m_textSize > 1 ? 1 : m_textSize;
for (int index = 0; index < m_showList.Count; index++)
{
var rt = m_showList[index];
if (rt != null)//排除空格
{
//设置字体尺寸和缩放
Vector2 size = rt.sizeDelta;
size.x *= m_textSize;
rt.sizeDelta = size;
rt.localScale = Vector3.one * m_textSize;
//设置字体间距
move += rt.rect.width / 2 + last / 2;
rt.anchoredPosition = new Vector2(move, 0);
last = rt.rect.width;
m_aniList.Add(rt.GetComponent<Animator>());
}
else
{
move += m_space;//空格
}
}
if (m_showList.Count > 0 && m_showList[0] != null) move += (int)m_showList[0].rect.width >> 1;
move = (int)move >> 1;
for (int index = 0; index < m_showList.Count; index++)
{
var obj = m_showList[index];
if (obj != null)
{
var pos = obj.anchoredPosition;
pos.x -= move;
obj.anchoredPosition = pos;
}
}
}
Transform InstantiateChild(string sChar, out float outSX)
{
var child = m_xxx.transform;
var childText = child.Find("Text");
TextMeshProUGUI textMeshProUGUI = childText.GetComponent<TextMeshProUGUI>();
textMeshProUGUI.text = sChar;
childText = childText.Find("Text");
textMeshProUGUI = childText.GetComponent<TextMeshProUGUI>();
textMeshProUGUI.text = sChar;
var rt = child.GetComponent<RectTransform>();
rt.SetActive(true);
Vector2 size = rt.sizeDelta;
float sx = size.x;
TMP_Text m_TextComponent = textMeshProUGUI.GetComponent<TMP_Text>();
m_TextComponent.havePropertiesChanged = true;
m_TextComponent.ForceMeshUpdate();
TMP_TextInfo textInfo = m_TextComponent.textInfo;
int characterCount = textInfo.characterInfo.Length;
if (characterCount > 0)
{
//sx = textInfo.characterInfo[0].ascender * textInfo.characterInfo[0].aspectRatio - textInfo.characterInfo[0].baseLine;
sx = textInfo.characterInfo[0].bottomRight.x - textInfo.characterInfo[0].bottomLeft.x;
}
size.x = sx;
rt.sizeDelta = size;
rt.SetActive(false);
outSX = size.x * 1.3f;
return GameObject.Instantiate(child, m_scroll.content.transform);
}
IEnumerator PlayAnimation()
{
yield return PlayShow();
PlayBeat();
}
IEnumerator PlayShow()
{
int playFinishNum = 0;
for (int i = 0; i < m_aniList.Count; i++)
{
var obj = m_aniList[i];
obj.SetActive(true);
obj.OnPlay("Show").OnComplete(() => { playFinishNum++; });
yield return new WaitForSecondsRealtime(0.05f);
}
yield return new WaitUntil(() => playFinishNum >= m_aniList.Count);
}
void PlayBeat()
{
for (int index = 0; index < m_aniList.Count; index++)
{
var obj = m_aniList[index];
obj.Play("Beat");
}
}
void ResetContent()
{
for (int index = 0; index < m_scroll.content.childCount; index++)
{
m_scroll.content.GetChild(index).SetActive(false);
}
}
public void OnClear()
{
for (int index = 0; index < m_showList.Count; index++)
{
var tran = m_showList[index];
m_showList.Remove(tran);
index--;
if(tran != null) GameObject.Destroy(tran.gameObject);
}
m_showList.Clear();
m_aniList.Clear();
}
}