1. 程式人生 > >Unity3d遊戲中實現阿拉伯語文字正常顯示

Unity3d遊戲中實現阿拉伯語文字正常顯示

return dex p s != 漢語 div 發現 3d遊戲 let

Unity3d遊戲中實現阿拉伯語文字正常顯示

由於項目需求要把遊戲文字顯示為維語版本(維語屬於阿拉伯語系),我先把維語替換進去,之後發現文字是錯的(每個字符都分開了,而且顯示方向也不對)後來在網上查了一下發現阿拉伯語是從右往左讀的,並且阿拉伯語的32個字符單說寫法就有126種(同一個字符有多種寫法)如下圖:

技術分享圖片

部分維語字符的不同書寫形式

首先我們來了解一下維語:

① 維文是以阿拉伯字母為基層的因素文字,由32個字母構成。分為元音、輔音兩大類。
② 8個元音又分三類;3個前元音、3個後元音、2個央元音。 每個詞的元音要麽都是前元音,要麽都是後元音。這8個元音中有4個同漢語元音等值完全相同,有4個相差較大。
③ 24個輔音又分為兩類;分別為:10個清音、14個濁音。這24個輔音中有20個同漢語聲母輔音等值完全相同,有4個相差較大。
④ 註有“新維文”字樣的框格,代表發音相差較大。

書寫規則:

【單立式】(又稱獨立式、獨寫體)用於詞末尾單獨構成一個音節時。
【後連式】(又稱連首體)用於詞首或音節首。
【雙連式】(又稱前後連式、中連式、連中體)用於兩種書寫形式的輔音字母之外的其余輔音字母的中間。
【隔音雙連式】(又稱隔音前後連式)用於詞中的音節首。
【前連式】(又稱連尾體)用於詞末尾與前面的字母相連。
【隔音前連式】用於詞末尾與前面的字母連寫單獨構成一個音節。
【簡單單立式】用於詞末尾而且是兩種書寫形式的輔音字母之後。
【簡單後連式】用於詞中間而且是兩種書寫形式的輔音字母之後。

上面這都是在網上看到的怎麽感覺有點像我們小時候學習 a o e 一樣了呢,哈哈.. 不得不說,真的看不懂!

其實看到這些字符我是一臉懵逼,不是龍舟就是戰艦的,最主要的是不認識。

最開始我是在網上找了個插件(如果在看到我這篇博客之前你查過阿拉伯語的顯示問題,你一定也在GitHub上看到過ArabicSupport這個插件吧),它不過也就是把文字顯示方向可以修改過來,但是裏邊還是存在很多問題的,後來修改了他的源碼,這才把項目裏的阿拉伯語正常顯示出來!當你仔細看他demo源碼的時候就會發現,他的做法是把一句話的每個字符分別存到兩個數組裏,然後用Unicode編碼進行比對、替換。打開一個阿拉伯語字體你會看到每一個字符都會有它對應的Unicode編碼。如下圖:

技術分享圖片 技術分享圖片

圖一 圖二

圖二中一套字體裏為什麽會有長得一樣的字符呢?點開一個字符,然後左下角你會發現對應的Unicode編碼是不同的,並且一個是獨立形式,另一個是非獨立形式。然而那些錯誤的字符就是因為使用的非獨立形式,才導致再次變形的時候出現錯誤,我們要做的就是要把這些讀取出來的非獨立形式轉換為獨立形式,做好映射

然後在GitHub那個Demo的源碼中我們看到他裏面提供了幾個接口,分別是判斷當前字符要使用前連書體、後邊書體、還是前後連書體或獨立書體,修改代碼如下:

  1     /// <summary>
  2     /// Checks if the letter at index value is a leading character in Arabic or not.
  3     /// </summary>
  4     /// <param name="letters">The whole word that contains the character to be checked</param>
  5     /// <param name="index">The index of the character to be checked</param>
  6     /// <returns>True if the character at index is a leading character, else, returns false</returns>
  7     internal static bool IsLeadingLetter(char[] letters, int index)
  8     {
  9 
 10         bool lettersThatCannotBeBeforeALeadingLetter = index == 0 
 11             || letters[index - 1] ==   
 12                 || letters[index - 1] == * // ??? Remove?
 13                 || letters[index - 1] == A // ??? Remove?
 14                 || char.IsPunctuation(letters[index - 1])
 15                 || char.IsNumber(letters[index - 1])
 16                 || letters[index - 1] == > 
 17                 || letters[index - 1] == < 
 18                 || letters[index - 1] == (int)IsolatedArabicLetters.Alef
 19                 || letters[index - 1] == (int)IsolatedArabicLetters.Dal 
 20                 || letters[index - 1] == (int)IsolatedArabicLetters.Thal
 21                 || letters[index - 1] == (int)IsolatedArabicLetters.Ra2 
 22                 || letters[index - 1] == (int)IsolatedArabicLetters.Zeen 
 23                 || letters[index - 1] == (int)IsolatedArabicLetters.PersianZe
 24                 //|| letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksora 
 25                 || letters[index - 1] == (int)IsolatedArabicLetters.Waw
 26                 || letters[index - 1] == (int)IsolatedArabicLetters.AlefMad 
 27                 || letters[index - 1] == (int)IsolatedArabicLetters.AlefHamza
 28                 || letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksoor 
 29                 || letters[index - 1] == (int)IsolatedArabicLetters.WawHamza
 30                 || letters[index - 1] == (int)IsolatedArabicLetters.Ae
 31                 || letters[index - 1] == (int)IsolatedArabicLetters.U
 32                 || letters[index - 1] == (int)IsolatedArabicLetters.Yu
 33                 || letters[index - 1] == (int)IsolatedArabicLetters.Oe
 34                 || letters[index - 1] == (int)IsolatedArabicLetters.Ve;
 35 
 36         bool lettersThatCannotBeALeadingLetter = letters[index] !=   
 37             && letters[index] != (int)IsolatedArabicLetters.Dal
 38             && letters[index] != (int)IsolatedArabicLetters.Thal
 39                 && letters[index] != (int)IsolatedArabicLetters.Ra2 
 40                 && letters[index] != (int)IsolatedArabicLetters.Zeen 
 41                 && letters[index] != (int)IsolatedArabicLetters.PersianZe
 42                 && letters[index] != (int)IsolatedArabicLetters.Alef 
 43                 && letters[index] != (int)IsolatedArabicLetters.AlefHamza
 44                 && letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
 45                 && letters[index] != (int)IsolatedArabicLetters.AlefMad
 46                 && letters[index] != (int)IsolatedArabicLetters.WawHamza
 47                 && letters[index] != (int)IsolatedArabicLetters.Waw
 48                 && letters[index] != (int)IsolatedArabicLetters.Hamza
 49                 && letters[index] != (int)IsolatedArabicLetters.Ae
 50                 && letters[index] != (int)IsolatedArabicLetters.U
 51                 && letters[index] != (int)IsolatedArabicLetters.Yu
 52                 && letters[index] != (int)IsolatedArabicLetters.Oe
 53                 && letters[index] != (int)IsolatedArabicLetters.Ve;
 54 
 55         bool lettersThatCannotBeAfterLeadingLetter = index < letters.Length - 1 
 56             && letters[index + 1] !=  
 57                 && !char.IsPunctuation(letters[index + 1] )
 58                 && !char.IsNumber(letters[index + 1])
 59                 && !char.IsSymbol(letters[index + 1])
 60                 && !char.IsLower(letters[index + 1])
 61                 && !char.IsUpper(letters[index + 1])
 62                 && letters[index + 1] != (int)IsolatedArabicLetters.Hamza;
 63 
 64         if(lettersThatCannotBeBeforeALeadingLetter && lettersThatCannotBeALeadingLetter && lettersThatCannotBeAfterLeadingLetter)
 65         {
 66             return true;
 67         }
 68         else
 69             return false;
 70     }
 71 
 72     /// <summary>
 73     /// Checks if the letter at index value is a finishing character in Arabic or not.
 74     /// </summary>
 75     /// <param name="letters">The whole word that contains the character to be checked</param>
 76     /// <param name="index">The index of the character to be checked</param>
 77     /// <returns>True if the character at index is a finishing character, else, returns false</returns>
 78     internal static bool IsFinishingLetter(char[] letters, int index)
 79     {
 80         bool indexZero = index != 0;
 81         bool lettersThatCannotBeBeforeAFinishingLetter = (index == 0) ? false : 
 82                 letters[index - 1] !=  
 83                 && letters[index - 1] != (int)IsolatedArabicLetters.Dal 
 84                 && letters[index - 1] != (int)IsolatedArabicLetters.Thal
 85                 && letters[index - 1] != (int)IsolatedArabicLetters.Ra2 
 86                 && letters[index - 1] != (int)IsolatedArabicLetters.Zeen 
 87                 && letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
 88                 //&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora 
 89                 && letters[index - 1] != (int)IsolatedArabicLetters.Waw
 90                 && letters[index - 1] != (int)IsolatedArabicLetters.Alef 
 91                 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
 92                 && letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza 
 93                 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
 94                 && letters[index - 1] != (int)IsolatedArabicLetters.WawHamza 
 95                 && letters[index - 1] != (int)IsolatedArabicLetters.Hamza
 96                 && letters[index - 1] != (int)IsolatedArabicLetters.Ae
 97                 && letters[index - 1] != (int)IsolatedArabicLetters.U
 98                 && letters[index - 1] != (int)IsolatedArabicLetters.Yu
 99                 && letters[index - 1] != (int)IsolatedArabicLetters.Oe
100                 && letters[index - 1] != (int)IsolatedArabicLetters.Ve
101 
102 
103                 && !char.IsNumber(letters[index - 1])
104                 && !char.IsPunctuation(letters[index - 1]) 
105                 && letters[index - 1] != > 
106                 && letters[index - 1] != <;
107                 
108 
109         bool lettersThatCannotBeFinishingLetters = letters[index] !=   && letters[index] != (int)IsolatedArabicLetters.Hamza;
110 
111     
112 
113 
114         if(lettersThatCannotBeBeforeAFinishingLetter && lettersThatCannotBeFinishingLetters)
115         {
116             return true;
117         }
118         else
119             return false;
120     }
121 
122     /// <summary>
123     /// Checks if the letter at index value is a middle character in Arabic or not.
124     /// </summary>
125     /// <param name="letters">The whole word that contains the character to be checked</param>
126     /// <param name="index">The index of the character to be checked</param>
127     /// <returns>True if the character at index is a middle character, else, returns false</returns>
128     internal static bool IsMiddleLetter(char[] letters, int index)
129     {
130         bool lettersThatCannotBeMiddleLetters = (index == 0) ? false : 
131             letters[index] != (int)IsolatedArabicLetters.Alef 
132                 && letters[index] != (int)IsolatedArabicLetters.Dal
133                 && letters[index] != (int)IsolatedArabicLetters.Thal 
134                 && letters[index] != (int)IsolatedArabicLetters.Ra2
135                 && letters[index] != (int)IsolatedArabicLetters.Zeen 
136                 && letters[index] != (int)IsolatedArabicLetters.PersianZe 
137                 //&& letters[index] != (int)IsolatedArabicLetters.AlefMaksora
138                 && letters[index] != (int)IsolatedArabicLetters.Waw 
139                 && letters[index] != (int)IsolatedArabicLetters.AlefMad
140                 && letters[index] != (int)IsolatedArabicLetters.AlefHamza 
141                 && letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
142                 && letters[index] != (int)IsolatedArabicLetters.WawHamza 
143                 && letters[index] != (int)IsolatedArabicLetters.Hamza
144                 && letters[index] != (int)IsolatedArabicLetters.Ae
145                 && letters[index] != (int)IsolatedArabicLetters.U
146                 && letters[index] != (int)IsolatedArabicLetters.Yu
147                 && letters[index] != (int)IsolatedArabicLetters.Oe
148                 && letters[index] != (int)IsolatedArabicLetters.Ve;
149 
150         bool lettersThatCannotBeBeforeMiddleCharacters = (index == 0) ? false :
151                 letters[index - 1] != (int)IsolatedArabicLetters.Alef 
152                 && letters[index - 1] != (int)IsolatedArabicLetters.Dal
153                 && letters[index - 1] != (int)IsolatedArabicLetters.Thal 
154                 && letters[index - 1] != (int)IsolatedArabicLetters.Ra2
155                 && letters[index - 1] != (int)IsolatedArabicLetters.Zeen 
156                 && letters[index - 1] != (int)IsolatedArabicLetters.PersianZe 
157                 //&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora
158                 && letters[index - 1] != (int)IsolatedArabicLetters.Waw 
159                 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
160                 && letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza 
161                 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
162                 && letters[index - 1] != (int)IsolatedArabicLetters.WawHamza 
163                 && letters[index - 1] != (int)IsolatedArabicLetters.Hamza
164                 && letters[index - 1] != (int)IsolatedArabicLetters.Ae
165                 && letters[index - 1] != (int)IsolatedArabicLetters.U
166                 && letters[index - 1] != (int)IsolatedArabicLetters.Yu
167                 && letters[index - 1] != (int)IsolatedArabicLetters.Oe
168                 && letters[index - 1] != (int)IsolatedArabicLetters.Ve
169                 && !char.IsNumber(letters[index - 1])
170                 && !char.IsPunctuation(letters[index - 1])
171                 && letters[index - 1] != > 
172                 && letters[index - 1] != < 
173                 && letters[index - 1] !=   
174                 && letters[index - 1] != *;
175 
176         bool lettersThatCannotBeAfterMiddleCharacters = (index >= letters.Length - 1) ? false :
177             letters[index + 1] !=   
178                 && letters[index + 1] != \r 
179                 && letters[index + 1] != (int)IsolatedArabicLetters.Hamza
180                 && !char.IsNumber(letters[index + 1])
181                 && !char.IsSymbol(letters[index + 1])
182                 && !char.IsPunctuation(letters[index + 1]);
183         if(lettersThatCannotBeAfterMiddleCharacters && lettersThatCannotBeBeforeMiddleCharacters && lettersThatCannotBeMiddleLetters)
184         {
185             try
186             {
187                 if (char.IsPunctuation(letters[index + 1]))
188                     return false;
189                 else
190                     return true;
191             }
192             catch
193             {
194                 return false;
195             }
196             //return true;
197         }
198         else
199             return false;
200     }

對照維語的Unicode編碼總結出:

①獨立形式Unicode編碼的基礎之上加1就是前連書體

②獨立形式Unicode編碼的基礎之上加2就是後連書體

③獨立形式Unicode編碼的基礎之上加3就是前後連書體

前面做好映射,有了上面這三個方法就能正常顯示字符的書寫形式了!(主要就是前連、後連、前後連這幾種書寫形體,其他形體不再多說)

看一下效果圖:(文字看起來是不是舒服一些)

技術分享圖片

登錄效果圖

此篇文章經過自己歸納總結整理出來,僅供參考,如果大家有什麽好的修改方式,或是好的意見或建議歡迎留言、交流,一起探討!

Unity3d遊戲中實現阿拉伯語文字正常顯示