Unity 避免Text组件每行开头不是字符和空格,适配不同分辨率

using System.Collections;

using System.Collections.Generic;

using System.Text.RegularExpressions;

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// Text组件首行标点符号优化排版工具

/// 自动检测并处理行首标点符号,避免出现句首标点的尴尬排版

/// </summary>

public class TextSymbolWrap : MonoBehaviour

{

public Text textCom;

private string origStr;

private string replaceStr;

private string finalReplaceStr;

/// 标记不换行的空格(换行空格Unicode编码为/u0020,不换行的/u00A0)

public static readonly string Non_breaking_space = "\u00A0";

/// 用于匹配标点符号,为了不破坏富文本标签,所以只匹配指定的符号

private readonly string strPunctuation = @",。??!!...";

/// 用于存储text组件中的内容

private System.Text.StringBuilder TempText = null;

/// 用于存储text生成器中的内容

private IList<UILineInfo> TextLine;

private int screenWidth = 0;

private int screenHeight = 0;

//在替换后的文本最后面添加一个看不到的字符,以用于辨别当前输入的文本是不是原始文本

private string endString = " ";

private bool isReplacing = false;

private void OnEnable()

{

isReplacing = false;

CheckTextComponent();

CheckScreenSizeChange();

ReplaceTextFun();

}

void Update()

{

// 当屏幕分辨率发生变化时,恢复原文本并重新计算,防止排版错乱

if (CheckScreenSizeChange())

{

if (textCom != null && !string.IsNullOrEmpty(origStr))

{

textCom.text = origStr;

replaceStr = "";

finalReplaceStr = "";

}

}

CheckReplaceText();

}

private bool CheckScreenSizeChange()

{

if (Screen.width != screenWidth || Screen.height != screenHeight)

{

screenWidth = Screen.width;

screenHeight = Screen.height;

return true;

}

return false;

}

private void CheckTextComponent()

{

if (textCom == null)

{

textCom = this.gameObject.GetComponent<Text>();

}

}

private void CheckReplaceText()

{

if (textCom == null || !CheckTextIsChange()) return;

ReplaceTextFun();

}

private void ReplaceTextFun()

{

if (isReplacing) return;

replaceStr = "";

finalReplaceStr = "";

StartCoroutine("ClearUpPunctuationMode", textCom);

}

private bool CheckTextIsChange()

{

if (textCom == null) return false;

return !string.Equals(textCom.text, finalReplaceStr);

}

IEnumerator ClearUpPunctuationMode(Text _component)

{

isReplacing = true;

// 不能立刻进行计算,要等渲染完上一帧才计算,故延迟60毫秒(约两帧多)

yield return new WaitForSeconds(0.06f);

if (string.IsNullOrEmpty(_component.text))

{

isReplacing = false;

}

else

{

string tempTxt = _component.text;

bool isOrigStr = false;

// 如果结尾没有特指标记字符,就认为是业务刚赋的值(即原始字符串)

if (tempTxttempTxt.Length - 1.ToString() != endString)

{

origStr = tempTxt;

isOrigStr = true;

}

TextLine = _component.cachedTextGenerator.lines;

int ChangeIndex = -1;

TempText = new System.Text.StringBuilder(_component.text);

// 从1开始遍历,只看第二行及以后的首字符

for (int i = 1; i < TextLine.Count; i++)

{

UILineInfo lineInfo = TextLinei;

int startCharIdx = lineInfo.startCharIdx;

if (TempText.Length <= startCharIdx) continue;

bool IsPunctuation = Regex.IsMatch(TempTextstartCharIdx.ToString(), strPunctuation);

// 将换行空格改成不换行空格后,如果首字符是不换行空格同样需要调整

if (TempTextstartCharIdx.ToString() == Non_breaking_space)

{

IsPunctuation = true;

}

if (IsPunctuation)

{

ChangeIndex = startCharIdx;

// 回退操作:判断提前一个字符后当前首字符是否仍是标点

while (IsPunctuation)

{

ChangeIndex -= 1;

if (ChangeIndex < 0) break;

IsPunctuation = Regex.IsMatch(TempTextChangeIndex.ToString(), strPunctuation);

if (TempTextChangeIndex.ToString() == Non_breaking_space)

{

IsPunctuation = true;

}

}

if (ChangeIndex < 0) continue;

// 在合适的位置手动插入换行符

if (TempTextChangeIndex - 1 != '\n')

TempText.Insert(ChangeIndex, "\n");

}

}

replaceStr = TempText.ToString();

// 如果最终排版有改动

if (!string.Equals(tempTxt, replaceStr))

{

if (isOrigStr)

{

replaceStr += endString;

}

_component.text = replaceStr;

}

else

{

// 计算后结果一致,证明当前文本排版已合法,记录状态防止死循环重复验证

finalReplaceStr = replaceStr;

}

isReplacing = false;

}

}

}

相关推荐
叶帆13 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
久数君13 天前
AI三维建模工具“造形家”:地理场景三维化的高效解决方案
unity·glb·ai算法·ai三维建模工具·地图框选·造形家·城市建筑模型
会思考的猴子13 天前
Unity VFX 属性 Postion 和 TargetPostion
unity
hai31524754313 天前
九章编程法 · 猜数字游戏 (GW-BASIC 重构版) *
人工智能·microsoft·游戏引擎·游戏程序
心前阳光14 天前
Unity资源导入之自动化资源导入
unity·自动化·游戏引擎
心前阳光14 天前
Unity之2021.3.45f2c1发布安卓程序遇到的问题
android·unity·游戏引擎
纪纯14 天前
PicoVR Unity Integration SDK 3.4 常用交互API
unity·游戏引擎·vr·pico
龙智DevSecOps解决方案14 天前
3A 游戏优化技术栈:如何打通引擎级分析工具与 DevOps 持续集成管线?
unity·性能优化·游戏开发·技术美术·perforce·unrealengine
葛兰岱尔14 天前
从 SolidWorks 到 Three.js,从 Inventor 到 Unity——制造业CAD模型“几何-语义一体化“转换,不再是天方夜谭!
开发语言·javascript·unity
鼎艺创新科技14 天前
三维电子沙盘中OSGB倾斜摄影数据的加载与渲染
游戏引擎·cocos2d