首页 > 编程知识 正文

unity中ugui,Unity ugui

时间:2023-05-05 03:18:51 阅读:256366 作者:4237

       据说中文和阿拉伯文是两种最难学的语言,中文咱就不说了,来说说阿拉伯文。最近项目要适配阿拉伯文的显示,由于Unity的ugui对阿拉伯文显示并没有提供支持,还是要自己动手来做适配,着实费了一番功夫。本文介绍一下完整的适配方案,供大家一起参考。

阿拉伯文简介

       首先介绍下阿拉伯文,阿拉伯文的显示是右对齐、从右到左的,不仅是语序从右到左,就连一个单词的每个字符都是从右到左显示的。打个比方,用大写英文字母来代表阿拉伯字符,我们理解的"ABCD  EFG"(约定下文都用斜粗体表示我们理解的顺序)在阿拉伯文中就会显示成"GFE  DCBA"。

       另外,当阿拉伯文和英文、数字混排时,英文和数字的显示顺序又要恢复成从左到右。比如说,我们理解的"ABCD hello world EFG 123"(还是用大写英文字母来代表阿拉伯字符),就会显示成"123 GFE hello world DCBA"。

       除了顺序,阿拉伯文还有一个特点是,同一个字符有多种写法,根据这个字符是单词的开头、中间、结尾来选择不同的写法。再打个比方(还是用英文字母举例),字符A有三种写法:A(前连书体),a(前后连书体),(后连书体),那么单词"AAA"就会显示成"aA"。

       好了,上述就是阿拉伯文的特点所在,正因为这些与众不同的特点,我们需要经过适配处理才能在Unity中正常显示。

      (不得不感慨秦始皇的“书同文”太伟大了)

在哪里适配

       网上一些适配方案都是把字符串适配后再赋值给ugui的Text组件,通过修改数据来改变显示。

Text t;string str;t.text = ArabicFix(str);

       不过我觉得,数据和显示最好分开,所以我把适配放在ugui的Text源码中,在渲染的时候使用适配后的字符串。就是说,Text保存的字符串数据还是从左往右的(如"ABCD hello world EFG 123"),然后转换成从右往左的字符串("123 GFE hello world DCBA"),用后者来渲染。

protect string m_Text = String.Empty;private string m_ShowText = String.Empty;public virtual string text{ get { return m_Text; } set { ... m_Text = value; m_ShowText = ArabicFix(m_Text); ... }}protected override void OnPopulateMesh(VertexHelper toFill){ ... cachedTextGenerator.PopulateWithErrors(m_ShowText, settings, gameObject); ...} 适配方案

       完整的适配方案分为5步:字符书体转换、字符串反转、字符串富文本提纯、字符串换行修正、字符串富文本恢复,下面详细说下每个步骤。

字符书体转换

       书体转换这一步,我是用的网上的一个开源插件ArabicSupport(https://github.com/Konash/arabic-support-unity),原理就是先判断这个字符是词首,词中还是词尾,然后转换成对应的前连书体、前后连书体、后连书体(这三种书体在Unicode码中有一定规则)。

字符串反转

       上面提到的ArabicSupport插件也提供了字符串反转功能,但是略显复杂,效果不是很好,所以我自己重写了一个。很简单,就是用一个栈来处理英文和数字。

string ReverseStr(string str){ List<char> list = new List<char>{}; Stack<char> stack = new Stack<char>{}; for(int i = str.Length-1; i >= 0; --i) { if() // 如果是英文字母或者数字,或者是标点符号且前后都是英文或数字,进栈 { stack.Push(str[i]); } else { // 遇到阿拉伯字符了,先出栈 while(stack.Count > 0) { list.Add(stack.Pop()); } // 再插入阿拉伯字符 list.Add(str[i]); } } // 全部出栈 while(stack.Count > 0) { list.Add(stack.Pop()); } return new string(list.ToArray());} 字符串换行修正

       在说富文本提纯前,先说字符串换行修正。我们知道,ugui的Text组件是有自动换行功能的,但遇到阿拉伯文时,这个换行就出问题了。比如说,显示 "TTTTTTTT 123 GFE hello world DCBA"(从右往左读的阿拉伯字符串),自动换行时,会显示成下图,句首跑到第二行了。

TTTTTTTT 123 GFEhello world DCBA

        这个换行处理ugui没有开源,所以要自己处理,方法是处理字符串时,在适当的地方手动插入换行符'n'。把"TTTTTTTT 123 GFE hello world DCBA"先处理成"hello world DCBAnTTTTTTTT 123 GFE ",再用后者渲染,就能得到我们想要的效果。

hello world DCBATTTTTTTT 123 GFE 字符串富文本提纯

       按照上面的换行修正方法,由于是自己处理字符串,可能会把富文本截断,所以要提取富文本中的纯文本,用纯文本替换掉富文本得到纯文本字符串,然后对纯文本字符串进行换行修正。提取时用到了以下正则式来匹配:

提取富文本:(<b.+?b>)|(<size.+?size>)|(<color.+?color>)提取富文本中的纯文本:>[^<>]+< 字符串富文本恢复

       经过换行修正后,需要进行富文本的恢复,很简单,在需要恢复的字符子串前后加上富文本修饰词就好。

一个例子

       现有一个从左往右读的阿拉伯字符串"ABAB hello world ABA 123"(用大写字母代表阿拉伯字符)

       内存中表示为                            ABAB <color=#ff3520>hello world ABA</color> 123

       1、字符书体转换                      Aba <color=#ff3520>hello world Ab</color> 123

       2、字符串反转                         123 <color/>bA hello world<ff3520#=color> abA      (注意:反转时富文本也会反转)

       3、字符串富文本提纯                              123 bA hello world abA 

       4、字符串换行修正                                 hello world abAn123 bA

       5、字符串富文本恢复    <color=#ff3520> hello world</color> abAn123 <color=#ff3520>bA</color>

       渲染显示                                                        hello world abA

                                                                                            123 bA

写在最后

       经测试,这套方案完美解决了项目中的阿拉伯文适配问题。为了避免代码细节喧宾夺主,本文没有贴出代码,只说明了步骤和算法,供大家一起参考。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。