unity text 文本符号显示问题与打字机效果的结合

问题1:unity text显示文本时,符号可能显示在某行的开头的位置

问题2:打字机效果没有适配问题1的脚本

解决方法:

问题1:通过遍历text组件每一行数据(第二行开始),如果是符号,就在它之前的字符前添加换行符

问题2:适配上述脚本

脚本1 解决文本符号显示问题

TextSymbolFit.cs

csharp 复制代码
public class TextSymbolFit : Text
    {
        /// <summary>
        /// 用于匹配标点符号
        /// </summary>
        private readonly string strRegex = @"\p{P}";

        /// <summary>
        /// 用于存储text组件中的内容
        /// </summary>
        private System.Text.StringBuilder MExplainText = null;

        /// <summary>
        /// 用于存储text生成器中的内容
        /// </summary>
        private IList<UILineInfo> MExpalinTextLine;

        protected override void OnPopulateMesh(VertexHelper toFill)
        {
            base.OnPopulateMesh(toFill);
            StartCoroutine(MClearUpExplainMode(this, text));
        }
        private IEnumerator MClearUpExplainMode(Text _component, string _text)
        {
            _component.text = _text;
            yield return new WaitForEndOfFrame();

            MExplainText = new System.Text.StringBuilder(_component.text);
            MExpalinTextLine = _component.cachedTextGenerator.lines;

            int mChangeIndex;

            // 从第二行开始进行检测
            for (int i = 1; i < MExpalinTextLine.Count; i++)
            {
                try
                {
                    if (MExpalinTextLine[i].startCharIdx >= _component.text.Length) continue;
                    //首位是否有标点
                    bool match = Regex.IsMatch(MExplainText.ToString()[MExpalinTextLine[i].startCharIdx].ToString(), strRegex);

                    if (match)
                    {
                        mChangeIndex = MExpalinTextLine[i].startCharIdx - 1;
                        // 解决联系多个都是标点符号的问题
                        for (int j = MExpalinTextLine[i].startCharIdx - 1; j > 0; j--)
                        {
                            match = Regex.IsMatch(MExplainText.ToString()[j].ToString(), strRegex);
                            if (match)
                            {
                                mChangeIndex--;
                            }
                            else
                            {
                                break;
                            }
                        }

                        MExplainText.Insert(mChangeIndex, "\n");
                    }
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

            _component.text = MExplainText.ToString();
        }
    }

脚本2,适配TextSymbolFit脚本

UITextType.cs

csharp 复制代码
public class UITextType : MonoBehaviour
    {
        public delegate void OnComplete();

        [SerializeField] float defaultSpeed = 0.05f;

        private Text label;
        private string finalText = string.Empty;
        private Coroutine typeTextCoroutine;

        private static readonly string[] uguiSymbols = { "b", "i" };
        private static readonly string[] uguiCloseSymbols = { "b", "i", "size", "color" };

        private OnComplete OnCompleteCallback;

        private void InitText()
        {
            if (label == null) label = GetComponent<Text>();
        }

        public void Awake()
        {
            InitText();
        }

        public void SetText(string text, float speed = -1)
        {
            InitText();

            defaultSpeed = speed > 0 ? speed : defaultSpeed;
            finalText = ReplaceSpeed(text);
            label.text = "";

            if (typeTextCoroutine != null)
            {
                StopCoroutine(typeTextCoroutine);
                typeTextCoroutine = null;
            }

            typeTextCoroutine = StartCoroutine(InnerTypeText(text));
        }

        public void SkipTypeText()
        {
            if (typeTextCoroutine != null)
            {
                StopCoroutine(typeTextCoroutine);
                typeTextCoroutine = null;
            }

            label.text = finalText;

            OnCompleteCallback?.Invoke();
        }

        public IEnumerator InnerTypeText(string text)
        {
            string currentText = "";

            int length = text.Length;
            float speed = defaultSpeed;
            bool tagOpened = false;
            string tagType = "";

            for (int i = 0; i < length; i++)
            {
                currentText = "";

                //匹配speed
                if (text[i] == '[' && i + 6 < length && text.Substring(i, 7).Equals("[speed="))
                {
                    string parseSpeed = "";
                    for (int j = i + 7; j < length; j++)
                    {
                        if (text[j] == ']')
                        {
                            break;
                        }

                        parseSpeed += text[j];
                    }

                    if (!float.TryParse(parseSpeed, out speed))
                    {
                        speed = defaultSpeed;
                    }

                    i += 8 + parseSpeed.Length - 1;
                    continue;
                }

                bool symbolDetected = false;
                //匹配 <i> 或 <b>
                for (int j = 0; j < uguiSymbols.Length; j++)
                {
                    string symbol = string.Format("<{0}>", uguiSymbols[j]);
                    if (text[i] == '<' && i + 1 + uguiSymbols[j].Length < length && text.Substring(i, 2 + uguiSymbols[j].Length).Equals(symbol))
                    {
                        currentText += symbol;
                        i += (2 + uguiSymbols[j].Length) - 1;
                        symbolDetected = true;
                        tagOpened = true;
                        tagType = uguiSymbols[j];
                        break;
                    }
                }

                //匹配富文本color格式
                if (text[i] == '<' && i + 1 + 15 < length && text.Substring(i, 2 + 6).Equals("<color=#") && text[i + 16] == '>')
                {
                    currentText += text.Substring(i, 2 + 6 + 8);
                    i += (2 + 14) - 1;
                    symbolDetected = true;
                    tagOpened = true;
                    tagType = "color";
                }

                //匹配富文本size格式
                if (text[i] == '<' && i + 5 < length && text.Substring(i, 6).Equals("<size="))
                {
                    string parseSize = "";
                    for (var j = i + 6; j < length; j++)
                    {
                        if (text[j] == '>')
                        {
                            break;
                        }

                        parseSize += text[j];
                    }

                    if (int.TryParse(parseSize, out _))
                    {
                        currentText += text.Substring(i, 7 + parseSize.Length);
                        i += (7 + parseSize.Length) - 1;
                        symbolDetected = true;
                        tagOpened = true;
                        tagType = "size";
                    }
                }

                //匹配富文本结束 </i> </b> </size> </color>
                for (int j = 0; j < uguiCloseSymbols.Length; j++)
                {
                    string symbol = string.Format("</{0}>", uguiCloseSymbols[j]);
                    if (text[i] == '<' && i + 2 + uguiCloseSymbols[j].Length < length && text.Substring(i, 3 + uguiCloseSymbols[j].Length).Equals(symbol))
                    {
                        currentText += symbol;
                        i += (3 + uguiCloseSymbols[j].Length) - 1;
                        symbolDetected = true;
                        tagOpened = false;
                        break;
                    }
                }

                if (symbolDetected) continue;

                currentText += text[i];
                label.text += currentText + (tagOpened ? string.Format("</{0}>", tagType) : "");
                yield return new WaitForSeconds(speed);
            }

            typeTextCoroutine = null;
            OnCompleteCallback?.Invoke();
        }

        private string ReplaceSpeed(string text)
        {
            return Regex.Replace(text, @"\[speed=\d+(\.\d+)?\]", "");
        }

        public bool IsSkippable()
        {
            return typeTextCoroutine != null;
        }

        public void SetOnComplete(OnComplete onComplete)
        {
            OnCompleteCallback = onComplete;
        }
    }

    public static class UITypeTextUtility
    {
        public static void TypeText(this Text label, string text, float speed = 0.05f, UITextType.OnComplete onComplete = null)
        {
            if (!label.TryGetComponent<UITextType>(out var typeText))
            {
                typeText = label.gameObject.AddComponent<UITextType>();
            }

            typeText.SetText(text, speed);
            typeText.SetOnComplete(onComplete);
        }

        public static bool IsSkippable(this Text label)
        {
            if (!label.TryGetComponent<UITextType>(out var typeText))
            {
                typeText = label.gameObject.AddComponent<UITextType>();
            }

            return typeText.IsSkippable();
        }

        public static void SkipTypeText(this Text label)
        {
            if (!label.TryGetComponent<UITextType>(out var typeText))
            {
                typeText = label.gameObject.AddComponent<UITextType>();
            }

            typeText.SkipTypeText();
        }
    }
相关推荐
缺点内向3 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅4 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看5 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程5 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t5 小时前
ZIP工具类
java·zip
lang201509286 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan7 小时前
第10章 Maven
java·maven
百锦再7 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说7 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多7 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring