Text文本打字效果,TextMeshPro可以对应参考,差距不大,改改参数名就能用。改脚本原本被我集成到其他的程序集中,现在已经分离。
效果
实现功能
1.能够设置每行能够容纳的字数和允许的冗余
2.打字效果
3.每行打完上移
4.开头进入,结束弹出
5.行居中
脚本使用
属性 | 解释 |
---|---|
TypingSpeed | 打字速度(.s 每过多少时间打一个) |
RowShowMax | 一行显示的最大值 |
AllowRedundancy | 每行能够允许的冗余 |
IsUpdateText | 更新文本,默认不启动,勾选点击运行就更新 |
Text | 挂载text文本 |
OffsetY | 对每行上移的补偿 |
SaveMarqueeoriginPosition | 保存字幕整体的初始位置 |
TextCloseDelayTime | 字幕消失的时间(Obsolete) |
BottomShow | 需要挂载下方显示的整体 |
函数 | 功能 |
---|---|
UpdateText | 更新文本,需要再Update中调用 |
OnFinish | 更新完成,更新文本完成后调用的函数 |
OnTextUpdate(string) | 文本更新,在打字过程中如果发生文本更新需要调用的方法 |
OnTextReset | 文本重置 |
设置
** 1.物体设置 **
** 2.text文本设置 **
1.需要文字的size(如果有外描边的话)来计算字占据的行宽,来决定每行上移的距离
2.文本每行居中,但定格显示
代码
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;namespace YBZ {public class TypewriterEffect : MonoBehaviour {// 测试文本private readonly string text_test = "SVN中我需要维护的东西Scene; Scripts/Engine/WSC SteamingAsset/2DPivots.json Editor/WSCPivotEditor.cs \n 下方提示";[Header("文本显示"), Space(10)]public float typingSpeed = 0.2f; // 打字速度public int rowShowMax = 25; // 一行最大显示数量public int allowRedundancy = 6; // 允许的冗余数量public bool isUpdateText = false; // 是否播放public Text text; // 底部字幕[Range(-25, 25), Space(5)]public int offsetY = -3; // 第一行Y轴补偿public Vector3 saveMarqueeOriginPostion = new Vector3(0, -63, 0); // 下方字幕的原初位置private float textTimeCount = 0; // 更新用的计时器private string word = ""; //保存字幕private int currentPos = 0; // 打字字符索引private int LineBreakCount = 0; // 换行符计数private Vector3 saveTextLocatePostion; // 用于保存TextUI位置private bool isOriginPosition = true;void Update() {UpdateText();if (Input.GetMouseButtonDown(0)) {OnTextUpdate(text_test);}}// 文本更新private void UpdateText() {if (!isUpdateText) {return;}// 检查字幕是否位于原初位置if (isOriginPosition) {isOriginPosition = !isOriginPosition;BottomShow.transform.DOLocalMove(Vector3.zero, 1.0f);}BottomShow.SetActive(true);if (saveTextLocatePostion == Vector3.zero) {saveTextLocatePostion = text.rectTransform.localPosition;}if (word == "") {word = text.text;}textTimeCount += Time.deltaTime;if (textTimeCount > typingSpeed) {textTimeCount = 0;currentPos++;if (currentPos >= word.Length) {Debug.Log("播放完成");OnFinish();return;}text.text = word[..currentPos];//刷新文本显示内容if (word[currentPos - 1] == '\n') {Debug.Log("发现换行符");LineBreakCount++;// 每次遇到一个换行符就上移25个单位if (LineBreakCount == 1) {text.rectTransform.DOLocalMoveY(text.rectTransform.localPosition.y + 25 + offsetY, 1f);} else if (LineBreakCount != 1) {text.rectTransform.DOLocalMoveY(text.rectTransform.localPosition.y + 25, 1f);}}// 每次处理行超限int lineCount;if (LineBreakCount == 0) {lineCount = text.text.Length;} else {lineCount = text.text[text.text.LastIndexOf('\n')..].Length;}// 行超限if (lineCount > rowShowMax + allowRedundancy) {word = text.text + '\n' + word[text.text.Length..];}}}[Header("下方显示延迟消失的所需要的时间")]public float textCloseDelayTime = 2.0f;/// <summary>/// 下方提示游戏物体,在使用前预加载/// </summary>public GameObject BottomShow;public IEnumerator IE_TextCloseDelayTime(float time) {yield return new WaitForSeconds(time);BottomShow.SetActive(false);Debug.Log("下方显示已关闭");}public IEnumerator IE_OnTextReset(float time) {yield return new WaitForSeconds(time);OnTextReset();Debug.Log("文本恢复默认");isOriginPosition = true;BottomShow.transform.DOLocalMove(saveMarqueeOriginPostion, 1.0f);}// 文本更新完成 , 一旦确认关闭就不要再更新文本, 否侧会出现逻辑错误,如若在播放完毕后更新文本一定要在下方显示关闭后, 字幕回滚的时候不能更新文本.private void OnFinish() {isUpdateText = false;// 完成之后下方显示 延迟关闭, 位置回调// StartCoroutine(IE_TextCloseDelayTime(textCloseDelayTime));// 延迟文本重置位置StartCoroutine(IE_OnTextReset(textCloseDelayTime));text.rectTransform.DOLocalMove(saveTextLocatePostion + new Vector3(0, offsetY, 0), textCloseDelayTime);}// 文本更新, 一旦更新就是确定要开始播放(╯‵□′)╯︵┻━┻(你更新不是为了播放?)private void OnTextUpdate(string newtext) {text ??= GameObject.Find("字幕文字").gameObject.GetComponent<Text>();OnTextReset();word = newtext;// StartCoroutine(IE_OnTextReset(0.5f));BottomShow.SetActive(true);isUpdateText = true;}// 文本恢復默认: 索引为0, 换行符统计为0, LocalPostion恢复, 文本置空private void OnTextReset() {if (saveTextLocatePostion == Vector3.zero) {saveTextLocatePostion = text.rectTransform.localPosition;}text.rectTransform.localPosition = saveTextLocatePostion;text.text = "";LineBreakCount = 0;currentPos = 0;}// 初始化public void Init() {Debug.Log("文本更新初始化完成");}public void UnInit() {Debug.Log("文本控制结束");}private void OnDestroy() {UnInit();}}
}