直接将脚本挂载在Text Mesh Pro上,但是需要滚动的文本必须在Scroll View中,否侧会定位错误,还需要给Scroll View中看需求添加垂直或者水平布局的组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.EventSystems;
public class TextScroll : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
// TextMeshPro的文本框
private TextMeshProUGUI text;
private string saveStr; // 保存文本内容,可以保存,但是没有必要,需要实现动态文本
private Vector3 savePostion; // 保存文本位置
private Vector2 savesizeDelta; // 保存尺寸
private float saveMoveWeight;
private RectTransform rect; // 文本的方形转换器
[Tooltip("开启自动权重")]
public bool AutoMoveWeight = true;
// 如果开启自动权重那么对该变量修改不在起作用
[Tooltip("溢出文本移动的权重,会根据权重的值,来对溢出内容的多少进行加速")]
public float moveWeight = 3;
private void OnEnable() {
text = GetComponent<TextMeshProUGUI>();
rect = text.gameObject.GetComponent<RectTransform>();
Init();
}
///
/// 初始化文本内容
///
public void Init() {
saveStr = text.text;
savePostion = rect.position;
savesizeDelta = rect.sizeDelta;
saveMoveWeight = moveWeight;
}
private Coroutine coroutine; // 接收协程
///
/// 鼠标进入
///
/// 传入事件数据,鼠标位置等
public void OnPointerEnter(PointerEventData eventData)
{
// Debug.Log("鼠标进入开始文本滚动");
// saveStr = text.text;
// 是否存在截断
float fontsLenght = CalculateTextWidth(text);
if (fontsLenght < rect.sizeDelta.x ) return;
// 处理上一次退出后未完成恢复完成就再次进入
if (coroutine != null) {
StopCoroutine(coroutine);
Reset();
}
// 是否启动自动更新
if (AutoMoveWeight) {
moveWeight = (fontsLenght - rect.sizeDelta.x) / 100;
}
// 计算所需时间
float sumTime = (fontsLenght - rect.sizeDelta.x) / text.fontSize / moveWeight;
rect.sizeDelta = new Vector2(fontsLenght + 100, rect.sizeDelta.y);
coroutine = StartCoroutine(IETextScroll(sumTime, false));
}
///
/// 鼠标移出
///
///
public void OnPointerExit(PointerEventData eventData) {
// Debug.Log("text begine reset");
// 过滤
if (text == null || (coroutine == null && CalculateTextWidth(text) < rect.sizeDelta.x) || totalDistance == 0) return;
if (coroutine != null) { // 文本正在向左滚动
StopCoroutine(coroutine);
}
coroutine = StartCoroutine(IETextScroll(totalTime / 3, true));
// Reset();
}
///
/// 计算文本内容宽度
///
///
///
private float CalculateTextWidth(TextMeshProUGUI text) {
float width = text.preferredWidth;
return width;
}
private float totalDistance = 0;
private float totalTime = 0;
///
/// 文本滚动的协程
///
/// 协程运行时间
/// 是否是恢复时启动的协程
///
private IEnumerator IETextScroll(float time, bool isReset) {
// float moveSpeed = 0;
float perDistance = 0;
if (!isReset) {
while (time > 0) {
// Time.deltaTime 是一个不确定的量,需要每帧更新。
perDistance = moveWeight * text.fontSize * Time.deltaTime;
rect.position = new Vector3(rect.position.x - perDistance, rect.position.y);
time -= Time.deltaTime;
totalDistance += perDistance;
totalTime += Time.deltaTime;
yield return null;
}
} else { // 恢复
//moveSpeed = totalDistance / time;
//while (time > 0) {
// perDistance = moveSpeed * Time.deltaTime;
// rect.position = new Vector3(rect.position.x + perDistance, rect.position.y);
// time -= Time.deltaTime;
// yield return null;
//}
Reset();
}
// Debug.Log("移动权重: " + moveWeight + " 每次距离: " + totalDistance + " 花费时间: " + totalTime);
yield return null;
}
///
/// 恢复
///
private void Reset()
{
if (text == null) return;
// text.text = saveStr;
rect.position = savePostion;
rect.sizeDelta = savesizeDelta;
moveWeight = saveMoveWeight; // 采用自动权重时会再次自动计算权重
totalDistance = 0;
totalTime = 0;
}
}