1. 程式人生 > >解決Unity中,使用Ngui 的預設字型Arial,在部分Android裝置顯示中文不清楚,或者顯示不出來問題

解決Unity中,使用Ngui 的預設字型Arial,在部分Android裝置顯示中文不清楚,或者顯示不出來問題

Unity工程中的動態字型使用很方便,在一開始的工程中,為了減小遊戲包的大小,我們使用的是Unity內建的預設Arial字型,但是在遊戲上線測試後,很多玩家反饋個別機型字型顯示不完全,主要集中在 小米1代,OPPO,金立,中興等個別機型中。剛開始以為是NGUI的問題,經過幾天的問題排查,發現原來是Arial字型惹的禍。

Arial字型是西文字型,並不包含中文字型檔,在Unity中如果使用預設的Arial字型,在程式執行過程中如果遇到字型檔中沒有的字,程式就會從系統預設字型檔中查詢對應的文字,如果字型檔中也沒有這些字,那麼就會造成字型不顯示的現象,在android系統中Unity預設會去查詢名為DroidSansFallback的字型,這個字型是android預設的字型,但是因為android系統的可定製性,太過自由,很多手機廠商或者第三方rom愛好者為了追求個性化,會去修改預設字型,替換成其他的字型,android系統是根據字型的檔名稱DroidSansFallback.ttf來找這個字型的,所以修改者只用將想要使用的字型檔名稱改為DroidSansFallback.ttf就可以在android系統中使用了。但是Unity識別字體卻不是通過字型的檔名稱來識別的,而是通過字型內部的設定來識別,如下圖: 


這個字型是win8系統預設的字型,雙擊預覽能夠看到字型名稱是Aharoni,Unity就是通過這個名稱來找預設字型的,這就導致了那些被修改了預設字型的android系統無法顯示字型,(此現象也出現在個別window xp系統中)。

問題出現的原因找到了,那麼就容易解決了,我們只要找到一個不是太大的符合自己要求的字型,放入到unity中,所有使用Arial字型的地方,都換成自己新增的動態字型即可。 


1 Font Names 預設倒入的一個字型,這個地方會顯示這個字型的真實名字,這個引數的主要作用實際上是設定替代字型用的,當程式需要某一個字型時,首先會從當前字型查詢字元,如果沒有找到,會依次查詢FontNames列表裡的其他字型中的字元,直到找到,或者找完為止。例圖中中添的幾個替代字型MYingHeiGB18030C-Bold, Droid Sans, Droid Sans Fallback, LTHYSZK,第一個MYingHeiGB18030C-Bold是當前字型的名稱(可以不用填),第二個,第三個是android系統裡的字型,第四個是小米1代所使用的字型。

Incl.FontData 選項打上勾,在倒出包的時候會把該字型新增到包中,若不打勾,則不會將該字型打包,程式執行時就會從FontNames列表裡檢索需要的字型,如果沒有,字型就不會顯示。

如果你的遊戲中一直都在使用字型A,突然有天Boss說,這個字型不好看!給我換成B字型!苦逼的你該怎麼辦?一個一個改麼?其實通過上邊所說的兩個引數,把A字型的Incl.Font Data不勾選,然後將B字型的FontName 填入A的FontNames裡,而B字型的Incl.Font Data打勾,我們可以很巧妙的將字型A全部替換成B字型,同時打包的時候又保證了只有B字型。

因為Unity的預設字型Arial是如此的不爽,所以在此建議大家不要在工程中使用Arial字型(純英文遊戲除外)。下邊貼一個寫的批量替換NGUI中的Arial字型為指定字型的指令碼,將其放入Asset /Editor資料夾下,即可在導航欄生成工具選單:

  1. using UnityEngine;  
  2. using System.Collections;  
  3. using System.Collections.Generic;  
  4. using UnityEditor;  
  5. publicclass FontReplese  
  6. {  
  7. //批量替換場景中的字型
  8. [MenuItem ("Custom/Label/ChangeSceneLabel" )]  
  9. publicstatic void ChangeSceneFont ()  
  10. {  
  11. List<UILabel> labelList = NGUIEditorTools.FindAll<UILabel> ();  
  12. ChangeLabelFont ( labelList );  
  13. }  
  14. publicstatic void ChangeLabelFont ( List<UILabel> labelList )  
  15. {  
  16. Font mFont = NGUIEditorTools.LoadAsset<Font> ("Assets/font/DroidSansFallback.TTF" );//注意這個地方是要替換成的字型的路徑
  17. if ( mFont ==null )  
  18. {  
  19. Debug.LogError (" Font not found ! " );  
  20. return;  
  21. }  
  22. foreach (var label in labelList )  
  23. {  
  24. if ( label !=null && label.trueTypeFont != null && label.trueTypeFont.name == "Arial" )//這個地方的name可以改為原來的字型的名稱
  25. {  
  26. label.trueTypeFont = mFont;  
  27. }  
  28. }  
  29. Debug.LogError ( labelList.Count );  
  30. }  
  31. //改變選中的預設上邊的字型
  32. [MenuItem ("Custom/Label/ChangeSelectionLabelFont" )]  
  33. publicstatic void ChangeSelectObjFont ()  
  34. {  
  35. GetTypeList ();  
  36. //ChangeLabelFont ( );
  37. }  
  38. publicstatic List<UILabel> GetTypeList ()  
  39. {  
  40. Object[] objList =Selection.GetFiltered ( typeof ( Object ), SelectionMode.DeepAssets );  
  41. //Debug.LogError (Selection.activeObject.name);
  42. Debug.LogError ( objList.Length );  
  43. List<UILabel> tmpList = new List<UILabel> ();  
  44. foreach (var tmp in objList )  
  45. {  
  46. if ( ( tmpas GameObject ) !=null )  
  47. {  
  48. string assetstr =AssetDatabase.GetAssetPath ( tmp );  
  49. GameObject obj =PrefabUtility.InstantiatePrefab ( tmp ) as GameObject;  
  50. List<UILabel> tmpLabel = GetTypeIncludeChildren ( obj );  
  51. if ( tmpLabel.Count >0 )  
  52. {  
  53. ChangeLabelFont ( tmpLabel );try
  54. {  
  55. PrefabUtility.ReplacePrefab ( obj, tmp );  
  56. }  
  57. catch ( System.Exception ex )  
  58. {  
  59. Debug.LogError ( ex.ToString () + tmp.name );  
  60. }  
  61. //Debug.LogError ( AssetDatabase.RenameAsset ( assetstr, name ) );
  62. }  
  63. GameObject.DestroyImmediate ( obj );  
  64. }  
  65. }  
  66. AssetDatabase.SaveAssets ();  
  67. AssetDatabase.Refresh ();  
  68. return tmpList;  
  69. }  
  70. publicstatic List<UILabel> GetTypeIncludeChildren ( Object obj )  
  71. {  
  72. GameObject tmp = objas GameObject;  
  73. if ( tmp ==null )  
  74. {  
  75. //return new List<UILabel> ();
  76. }  
  77. List<UILabel> tmpList = new List<UILabel> ();  
  78. UILabel tmpLabel = tmp.GetComponent<UILabel> ();  
  79. if ( tmpLabel !=null )  
  80. {  
  81. tmpList.Add ( tmpLabel );  
  82. }  
  83. foreach (Transform child in tmp.transform )  
  84. {  
  85. tmpList.AddRange ( GetTypeIncludeChildren ( child.gameObject ) );  
  86. }  
  87. return tmpList;  
  88. }  
  89. }  


本指令碼僅支援替換NGUI的UILabel所使用的字型,經測試替換預設上的UILabel字型的方法在Unity4.3版本中會導致預設無法使用,但在Unity4.5.x中完美使用。