【游戏开发解答】Unity发布微信小游戏,中文字无法显示的问题(自制字体库

您所在的位置:网站首页 微信小游戏走方格怎么玩 【游戏开发解答】Unity发布微信小游戏,中文字无法显示的问题(自制字体库

【游戏开发解答】Unity发布微信小游戏,中文字无法显示的问题(自制字体库

2024-07-01 14:02| 来源: 网络整理| 查看: 265

文章目录 一、前言二、Unity默认的字体:Arial三、查看动态字体的动态纹理四、用动态字体还是静态字体1、用不用Arial动态字体2、用Dynamic还是Custom set 五、字体文件资源瘦身1、办法一:字体文件本身做裁剪2、办法二:制作静态字体 六、扫描工程中用到的字,自动设置Custom Chars1、配置表、代码文本扫描2、预设文本扫描3、通用标点符号、数字、字母4、字符去重5、执行扫描,自动设置customCharacters 七、微信小游戏中文显示问题

一、前言

嗨,大家好,我是林新发。 我使用Unity开发项目,然后发布成微信小游戏的时候遇到了一个问题:有部分中文字无法显示。 发现是因为个别界面预设中的Text使用了默认的Arial字体,为什么会出现中文字无法显示的问题呢? 我觉得有必要写篇文章讲讲。

注:可能有同学会问:Unity开发的项目可以直接发布微信小游戏吗?答案是可以滴,不过需要安装一个发布工具插件,插件GitHub地址:https://github.com/wechat-miniprogram/minigame-unity-webgl-transform 详细参见GitHub中的文档即可,如果有需要的话我再另外写文章讲解操作流程。

二、Unity默认的字体:Arial

Unity默认使用的字体是Arial,比如你用UGUI创建一个Text,你就会看到它使用的Font为Arial, 在这里插入图片描述 Arial是Windows的系统字体之一,Unity直接访问它,并以动态字体(Dynamic)的形式渲染。 Arial本身并不包含中文字库,为了证明Arial字体不包含中文字库,我使用FontCreator这个软件打开arial.ttf字体,然后预览窗口中输入Hello,我叫林新发,可以看到,中文字显示不了: 在这里插入图片描述

注:FontCreator这个软件可以从我的GitCode上免费下载:https://gitcode.net/linxinfa/fontmaker/-/blob/master/FontCreator.zip?from_codechina=yes 另外,我之前写过一篇关于字体裁剪的文章,里面有介绍这个软件的使用:《字体裁剪,精简字体,字体瘦身:FontSubsetGUI,FontCreator,FontPruner》

那Unity是怎么把中文显示出来的呢?我贴一段Unity官方手册的说明吧~

Unity官方手册: 当 Unity尝试使用 动态字体 渲染文本但无法找到字体时(因为未选择 Include Font Data__,并且用户计算机上未安装该字体),或者字体不包含请求的字形时(例如尝试使用拉丁字体在东亚脚本中渲染文本时,或者使用粗体/斜体字形文本时),它将尝试Font Names__字段中列出的每种字体,从而查看是否可以找到与项目中的字体名称匹配的字体(包含字体数据)或者用户计算机上安装的字体是否具有请求的字形。如果找不到列出的后备字体或者这些字体不具有所请求的字形,Unity将回退到硬编码的全局后备字体列表,其中包含当前运行时平台上通常安装的各种国际字体。

手册文档中提到的Include Font Data__和Font Names__字段,我们在Unity中选择字体文件,在Inspector面包中进行设置: 在这里插入图片描述

所以我们的中文并不是通过Arial这个字体来渲染的,而是通过其他系统字体来渲染的。

三、查看动态字体的动态纹理

跟3D模型的渲染类似,文字的渲染过程也是GPU通过网格、纹理、材质等信息计算绘制出来的, 请添加图片描述 动态字体 是在运行时动态创建字的纹理,并且当出现字体库中不存在的字时,会从系统的默认字体库中查找对应的文字。

注:如果系统默认的字库中也没有这个字,就会造成字体不显示的问题。

我们创建一个Text,使用默认的Arial动态字体,如下 在这里插入图片描述 我们可以看到英文和中文都能正常显示, 在这里插入图片描述

接着,我们打开Frame Debugger, 在这里插入图片描述 可以看到渲染文字时它动态生成了一张Font Texture,不过在Frame Debugger中看不清, 在这里插入图片描述 没关系,我们可以通过代码把这张纹理图取出来显示到界面中。我们先创建一个RawImage,用于显示字体纹理, 在这里插入图片描述

然后创建一个Main.cs脚本,代码如下:

using UnityEngine; using UnityEngine.UI; public class Main : MonoBehaviour { public Text text; public RawImage img; void Start() { img.texture = text.font.material.mainTexture; } }

把Main.cs脚本挂到Canvas节点上,并赋值Text和RawImage对象,如下, 在这里插入图片描述 运行Unity,现在可以看清字体的纹理啦, 在这里插入图片描述 现在我们来玩个好玩的,我动态调整Text的字号,可以看到它动态生成了不同字号的纹理,如下 请添加图片描述 这就是为什么我们使用动态字体时,不同字号的字清晰度不同的原因,它会根据你字号所在的段位查找匹配的纹理进行渲染。

四、用动态字体还是静态字体

用动态字体还是静态字体,这个问题要具体情况具体分析。

1、用不用Arial动态字体

如果你的项目是纯英文的项目,你可以使用默认的Arial动态字体,否则不要使用默认的Arial动态字体,原因如下:

不同平台的系统默认字体不同,比如在Android系统中Unity3D默认会去查找名为DroidSansFallback的字体,但是因为Android系统的可定制性,很多手机厂商会去修改默认字体。Android系统是根据字体的文件名称来找字体的,但Unity3D识别字体却是通过字体内部的设置来识别字体的,所以即使在Android手机中有DroidSansFallback.ttf字体,也有可能导致Unity3D找不到这个字体。由于上面的原因,尽量不要使用Unity3D的默认字体Arial,除非你做的游戏是纯英文的。

2、用Dynamic还是Custom set

自己导入一个TTF字体,是用Dynamic还是用Custom set呢? 在这里插入图片描述 我们先来做个实验,以这个这个Dengb.ttf字体为例,它有15M这么大(实际项目不会用这么大的字体,会做一些处理,下文会讲解决办法), 在这里插入图片描述 假设我们使用Dynamic,并且勾选的了Incl. Font Data,如下, 在这里插入图片描述 现在我们使用Addressables系统,把它单独放在一个Group中,如下

注:关于Addressables系统,我之前写过一篇教程,可以参见我之前的这篇文章:《【游戏开发探究】Unity Addressables资源管理方式用起来太爽了,资源打包、加载、热更变得如此轻松(Addressable Asset System | 简称AA)》

在这里插入图片描述 现在们打包资源,看生成的.bundle文件大小,有11.1M那么大, 在这里插入图片描述 我们使用AssetStudio逆向这个.bundle文件,可以看到它包含了完整的字体文件数据和一张空纹理, 请添加图片描述

如果字体放在包内,你的包体就会变大,如果你是动态下载,那么就要下载十几兆的字体bundle,这对于存储空间和资源下载都不是很友好,当然,如果你不在乎这点存储空间和下载时间,可以不用管~

五、字体文件资源瘦身

有没有缩小字体文件的办法呢?有两种解决办法。

1、办法一:字体文件本身做裁剪

对ttf字体本身做裁剪瘦身,我之前写过一篇教程,可以参见我这篇文章:《字体裁剪,精简字体,字体瘦身:FontSubsetGUI,FontCreator,FontPruner》 字体设置上依然使用Dynamic。

2、办法二:制作静态字体

制作静态字体,也就是使用Custom set。下面我着重讲下这种办法。 注意,如果使用静态字体,当出现不存在的字形时,Unity并不会像动态字体那样去帮我们查询后备字体和系统字体,所以会导致文字无法正常渲染。 所以这里就涉及到一个问题,我们使用Custom set,要填写的Custom Chars该填多少个字呢? 在这里插入图片描述 不管三七二十一,把所有的汉字都填进去,那是不科学的,咱们就拿1994年出版的《中华字海》来说,它收字有85,568个,全放进去,生成的纹理该有多大啊。 一般我们只会放常用的8000汉字、英文字母、数字、标点符号等,设置Font Size为60,即使这样,生成的纹理尺寸已经达到极限的 4096 x 4096,有16M这么大, 在这里插入图片描述 可以酌情得把常用汉字减少一些,比如减到5000字,另外,如果你非常确定所需要显示的字量,比如我非常明确只用到了Hello,林新发这几个字,Custom Chars中我就只需要填Hello,林新发这几个字, 在这里插入图片描述 生成的纹理只有32KB, 在这里插入图片描述 我们运行时动态修改Text的字号,可以发现它始终都是引用静态字体的纹理,不会像动态字体那样动态生成纹理,字号的调整仅仅只是做纹理的缩放,当缩放过大时就会显得模糊, 请添加图片描述 另外,由于纹理是静态的,Text的Font Style只能是Normal,不能设置斜体、粗体等, 在这里插入图片描述

现在,我们使用Addressables系统重新打包资源,可以看到生成的.bundle只有8.13KB, 在这里插入图片描述 我们使用Asset Studio逆向bundle文件,可以看到里面存放这我们的32KB纹理和470B的字体信息,这样就大大减少了字体文件的资源大小了, 在这里插入图片描述 那么问题又来了,我们如何确定工程中到底用到了哪些字呢?我们可以写工具去扫描整个工程。

六、扫描工程中用到的字,自动设置Custom Chars

一般我们工程中使用到的文字,会散落在以下一些地方:配置表、代码写死的字符串、预设中摆放的Text、预设中挂的MonoBehaviour脚本的string类型的成员变量等。

以下示例代码需引入的命名空间:

using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; using UnityEngine.UI; using System.Text; using System.Reflection; 1、配置表、代码文本扫描

配置表和代码的扫描,可以使用正则表达式匹配,如果懒的话,直接全部字符文本都读出来,以扫描json配置表为例:

// 配置文本扫描 public string ScanJsonCfg() { StringBuilder sbr = new StringBuilder(); string[] fs = Directory.GetFiles(Application.dataPath + "/Config", "*.json", SearchOption.AllDirectories); for (int i = 0, flen = fs.Length; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3