Unity UGUI 数字使用图片显示-BMFont

Unity UGUI 数字使用图片显示-BMFont

BMFont

之前使用Cocos引擎的时候需要用到艺术字也就是将数字使用美术给的图片来代替显示,也就是要做一个新字体专门用来显示艺术字,当时用的是BMFont来制作字体。那么问题来了,在Unity下面的UGUI能否使用呢?答案当然是OK的啦。

下面我们来看下如何使用BMFont。

从网站https://www.angelcode.com/products/bmfont/下载并安装BMFont软件。

制作

我们通过菜单栏“Edit/Open Image Manager”来选择需要做艺术字的图片。

Unity UGUI 数字使用图片显示-BMFont_第1张图片

打开之后选择”Image/Import image“

Unity UGUI 数字使用图片显示-BMFont_第2张图片

点击”Browse“按钮选择数字0的png图片,然后在Id一栏填写该数字的Id也就是如下的箭头所示的48,即数字0的ASCII码。

Unity UGUI 数字使用图片显示-BMFont_第3张图片

Unity UGUI 数字使用图片显示-BMFont_第4张图片

点击OK就会将图片给导入进来。

导入的图片不显示

但是需要注意这个时候可能会出现点击之后Image Manager面板里面并没有出现刚才加载的图片。这里是美术给的图片格式不对,我们需要将png图片修改为PNG-24格式的。打开PS加载出对应点png图片,然后菜单栏选择“文件/存储为Web所用格式”。

Unity UGUI 数字使用图片显示-BMFont_第5张图片

在弹出的面板图中所示的位置选择PNG-24格式,点击存储即可。

Unity UGUI 数字使用图片显示-BMFont_第6张图片

我们依次添加完所有的数字png图片之后,在BMFont的菜单栏“Options/Export options”里面设置一下导出的参数。

Unity UGUI 数字使用图片显示-BMFont_第7张图片

图片的Width和Height可以自己根据里面的图片大小自己设置(设置好之后可以不必着急关闭窗口,在导出时候查看生产的所有的数字合并之后的图片大小是否合适,里面的数字排版是否紧凑。一开始设置大了或者小了,后面还可以修改大小,重新导出)。

Unity UGUI 数字使用图片显示-BMFont_第8张图片

下面的Font description 更改为XML,后面需要根据这个格式生成对应的字体文件。然后Texture格式设置为png。点击Ok即可。接下来就是回到BMFont的菜单栏选择“Options/Save bitmap font as…”即可保存出Score.fnt文件,同时生成的还有一个对应的png大图。

Unity UGUI 数字使用图片显示-BMFont_第9张图片

我们将生成的Score.fnt和Score_0.png一起放入Unity中,然后新建一个BitmapFontExporter.cs文件放入Unity的Editor目录,代码如下:

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Xml; 
using System;

public class BitmapFontExporter : ScriptableWizard
{
    [MenuItem("BitmapFontExporter/Create")]
    private static void CreateFont()
    {
        ScriptableWizard.DisplayWizard("Create Font");
    }


    public TextAsset fontFile;
    public Texture2D textureFile;

    private void OnWizardCreate()
    {
        if (fontFile == null || textureFile == null)
        {
            return;
        }

        string path = EditorUtility.SaveFilePanelInProject("Save Font", fontFile.name, "", "");

        if (!string.IsNullOrEmpty(path))
        {
            ResolveFont(path);
        }
    }


    private void ResolveFont(string exportPath)
    {
        if (!fontFile) throw new UnityException(fontFile.name + "is not a valid font-xml file");

        Font font = new Font();
        
        XmlDocument xml = new XmlDocument();
        xml.LoadXml(fontFile.text);

        XmlNode info = xml.GetElementsByTagName("info")[0];
        XmlNodeList chars = xml.GetElementsByTagName("chars")[0].ChildNodes;

        CharacterInfo[] charInfos = new CharacterInfo[chars.Count];

        for (int cnt = 0; cnt < chars.Count; cnt++)
        {
            XmlNode node = chars[cnt];
            CharacterInfo charInfo = new CharacterInfo();

            charInfo.index = ToInt(node, "id");
            charInfo.width = ToInt(node, "xadvance");
            charInfo.uv = GetUV(node);
            charInfo.vert = GetVert(node);

            charInfos[cnt] = charInfo;
        }


        Shader shader = Shader.Find("Unlit/Transparent");
        Material material = new Material(shader);
        material.mainTexture = textureFile;
        AssetDatabase.CreateAsset(material, exportPath + ".mat");


        font.material = material;
        font.name = info.Attributes.GetNamedItem("face").InnerText;
        font.characterInfo = charInfos;
        AssetDatabase.CreateAsset(font, exportPath + ".fontsettings");
    }


    private Rect GetUV(XmlNode node)
    {
        Rect uv = new Rect();

        uv.x = ToFloat(node, "x") / textureFile.width;
        uv.y = ToFloat(node, "y") / textureFile.height;
        uv.width = ToFloat(node, "width") / textureFile.width;
        uv.height = ToFloat(node, "height") / textureFile.height;
        uv.y = 1f - uv.y - uv.height;

        return uv;
    }


    private Rect GetVert(XmlNode node)
    {
        Rect uv = new Rect();

        uv.x = ToFloat(node, "xoffset");
        uv.y = ToFloat(node, "yoffset");
        uv.width = ToFloat(node, "width");
        uv.height = ToFloat(node, "height");
        uv.y = -uv.y;
        uv.height = -uv.height;

        return uv;
    }


    private int ToInt(XmlNode node, string name)
    {
        return Convert.ToInt32(node.Attributes.GetNamedItem(name).InnerText);
    }


    private float ToFloat(XmlNode node, string name)
    {
        return (float)ToInt(node, name);
    }
}

然后我们在Unity的菜单栏选择“BitmapFontExporter/Creat”即可打开字体创建面板。

Unity UGUI 数字使用图片显示-BMFont_第10张图片

在打开的面板中将生成的XML文件和png大图拖拽进去,点击Create按钮即可生成Score字体。

Unity UGUI 数字使用图片显示-BMFont_第11张图片

在Unity中可以看到这张png大图里面的所有数字的排列紧凑程度,也就是上面提到的。

Unity UGUI 数字使用图片显示-BMFont_第12张图片

原理

Unity提供了一个自定义字体的方法,在Unity中右键“Create/Custom Font“会生成一个自定义的字体,不过需要我们手动去填写字体对应的材质球和Character Rects。size大小表示有多少个艺术字,然后要在每个Element里面的index填写字符对应的ASCII码,还要填写对应的UV和Vert。

Unity UGUI 数字使用图片显示-BMFont_第13张图片

不过这个过程相当繁琐,所以通过代码来完成这一步骤。原理很简单,就是将BMFont生成出来的XML配置文件读取出来,依次填写进去即可。

Unity UGUI 数字使用图片显示-BMFont_第14张图片

Unity UGUI 数字使用图片显示-BMFont_第15张图片

使用

在UGUI的Text组件里面选择刚才生成的字体拖拽进去即可,具体如下

Unity UGUI 数字使用图片显示-BMFont_第16张图片

Unity UGUI 数字使用图片显示-BMFont_第17张图片

参考:https://tedsieblog.wordpress.com/category/unity-ugui/

你可能感兴趣的:(Unity,技术实现)