项目用ngui制作的界面,字体使用了unity默认的Arial,发布后在一些android手机上发现中文不显示,就此作了一些调查。
参考unity的font说明文档:http://docs.unity3d.com/Manual/class-Font.html,http://game.ceeger.com/Components/class-Font.html(中文翻译版)
1.使用动态(Dynamic)字体:
好处,动态字基本包括所有字(中文等),大小可调,显示清晰,可用于动态文本。
unity方便的支持ttf,otf格式的字体,字体文件放到Assets目录下任何位置,untiy会自动为其生成材质和贴图。
导入的字体可以做一些设置,在文档里对每个都有解释。其中设置Character 为dynamic。
Include Font Data选中表示把该字体打包进安装包,然后安装到用户机器上去,如果用户机器自带有该字体,可以不打包进来,但是需要在Font Names指定系统要用到的字体顺序。(导入字体后Font Names属性会自动显示这个字体的名字,注意不是字体的文件名,字体名是该字体的系统标示名)
对于中文字体,选择Include Font Data的问题是字库太大,比如黑体有9M,雅黑10多M。会导致安装文件增大(9M黑打打包进unity将增大安装文件5M),如果项目要用到不止一种动态字体就更郁闷了,unity方便的支持ttf等字体对西文字符是个便利的事,对中文来讲还有瘦身等问题要处理。
如果不打包字体则需要保证系统中已经存在该字体,此时Font Names属性生效,在运行时自动从系统中寻找列表中的字体,直到找到为止。
如果使用unity默认动态字体Arial,对此的解释是发布到不同的平台后将默认使用当前平台的默认字体。在测试时发现在小米1的机器上,低版本miui系统里无法显示汉字,另一台高版本miui的小米手机可以显示Arial,simei等字体(不需要打包进安装文件),在一台魅族手机上测试也不能显示Arial。因此unity的Arial字体与平台的映射关系并不保险。
andriod系统有自己的默认字体Droid Sans(只含西文字符),和默认中文字体Droid Sans Fallback。unity把Arial字体在andriod平台上映射为Droid Sans (Fallback)。
在低版本miui系统(小米1)里可以看到只有一个中文字体文件DroidSansFallback.ttf,大小为2M多,拿出这个字体文件放到unity里能看到里面的字体名字是LTHYSZK。可能是因为字体名字被miui系统改成这个导致unity的Arial映射到andriod的失效。
在高版本miui系统里有多个中文字体文件,其中DroidSansFallback.ttf的大小变为4.4M,在unity里发现字体名字已经是Droid Sans Fallback了,可见unity的Arial映射到andriod确实和字体名字有关。(没有测试过把高版本ttf拿到低版本miui系统里去,貌似得刷机才能测?这个结论只是猜测)。
在高版本miui里多了几种中文字体,确实是属于系统定制的字体:
下面参考文章里有把andriod默认字体与微软雅黑做对比,得出两种字体很相似的结论,相比雅黑10M以上的体积,Droid Sans Fallback想对瘦小。不知道DroidSansFallback.ttf是否包含所有的中文字符,我用2M多的DroidSansFallback.ttf测试了一些偏僻字,也没有发现缺失。(如果想用雅黑,可以用这个来替代)
使用Arial的另外一个问题是,作为unity默认字体,unity不会把Arial真正打包进安装文件,无法找到这个字体源文件,无法更改Font Names属性,在找不到默认字体的系统里就会不显示中文了。
所以更好的一个做法是做空壳。导入一种字体但不打包到安装文件,设置好Font Names属性(包含各个平台的字体名列表),则在不同的平台上调用不同的字体。只要确保发布时指定的Font Names属性里有目标平台的字体就行。
要明白开发时当前显示的是导入的这个字体效果,但运行时会根据系统和平台以及Font Names的设置而效果不同。
打包进嵌入的字体则会表现效果一致,唯一的问题是安装文件会增大很多。
发布时发现的另外一个问题:
低版本ngui(3.0)选择Dynamic字体,Font列表里可以选择Lucida Grande字体,在发布到andriod和winpc系统时会报错无法发布:
原因是Lucida Grande是macos下的默认字体不可以发布到其他平台(应该在macos下也不让发布Arial字体吧),在当前操作系统windows下没有这种字体无法发布(貌似如此,没有从macos把Lucida Grande拿过来试验。参考下面一文)。这是低版本ngui设计的不好,ngui实际是没有动态字体的,它的动态字体实际就是调用unity的动态字体设置,自己只有位图字体。在升级ngui到3.5.6之后就发现字体选项只有ngui和unity,然后再选择具体用什么font,ngui终于有了自知之明,不再误导了。而且选择unity后会屏蔽掉非当前系统的字体选项,这点改进很好。
macos下用Lucida Grande字体(与雅黑接近),ios下默认是黑体-简Heiti SC(早期版本是华文黑体)。
参考:
编译时,遇到Couldn't build player because of unsupported data on target platform的解决方案
http://blog.csdn.net/monzart7an/article/details/24156661
Android字体简介
http://www.apkbus.com/android-58182-1-1.html
在android系统中,DroidSans是默认字体,只包含西方字符,应用程序默认情况下都会调用它,而DroidSansFallback包含了东亚字符,当需要显示的字符在DroidSans字体中不存在(如:汉字)时,即没有对应编码的字符时,系统会到DroidSansFallback中去找相应编码的字符,如果找到,则使用DroidSansFallback字体来显示它,如果仍找不到该编码对应的字符,则无法在屏幕上显示该字符。
关于 Android 默认字体以及对比微软雅黑字体
http://www.cnbeta.com/articles/114854.htm
2.bmfont
bitmap font位图字体是另外一种方案,把字符集做成atlas可以灵活使用各种字体,缺点是位图无法缩放有锯齿,而且中文字符一般只是引入一些常用字或者项目中用到的字,否则整个字符集太大,会占用太多内存,或者受unity atlas大小限制无法集成所有字符。
打开NGUI的bitmap font maker
NGUI 3.5.6以上版本可以方便制作bitmapfont,需要导入FreeType.dll,如果找不到这个文件无法制作位图字体。从NGUI的安装包import到项目中,它的默认位置是Assets/NGUI/Editor/FreeType.dll,我把这个文件挪走了需要重新找下它,下面有Find FreeType.dll按钮。
font maker可以从导入的ttf来制作bimapfont:我从source里选择导入的simhei,字符集里包含东南2个字。output atlas让指定字符集图片放到哪个已有的atlas图集中,不指定就会单独生成一张,不利于drawcall,最好很多bitmapfont图集公用一个。
我创建的字体叫heiti.prefab,因为是prefab用起来很方便,哪里都能用。
使用的时候选择NGUI,然后选择这个heiti字体,只有图集中有的字才会显示。