Unity 美术字图片 生成 字体Font

简介

有时候,美术会提供图片(大部分是数字效果),Unity需要在Text组件使用这些美术效果,这时候可以把这些图片制作成一个Font(字体文件),供Text使用。


一、使用BmFont工具


注:工具直接搜索下载即可,同时会有使用步骤教程!
使用BmFont工具最终产出两个资源:
.fnt :该文件是字符的配置
.png :相当于图片资源集合


二、使用编辑工具(Unity)生成最终资源

1、将生成的.fnt 和 .png 文件导入Unity
2、将.png 在Inspector面板中将Texture Type设置成Sprite(2D and UI)
3、打开编辑器工具(编辑器代码见文章下方)
在这里插入图片描述
Font Texture:选择上边导入设置成的Sprite
BMFont fnt:选择.fnt文件
最后点击生成。

4、生成结果:
在这里插入图片描述

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;


public class BMFontEditor : EditorWindow
{
    public TextAsset fontPosTbl;
    public Texture fontTexture;
    public Vector2 scrollPos;

    struct ChrRect
    {
        public int id;
        public int x;
        public int y;
        public int w;
        public int h;
        public int xofs;
        public int yofs;

        public int index;
        public float uvX;
        public float uvY;
        public float uvW;
        public float uvH;
        public float vertX;
        public float vertY;
        public float vertW;
        public float vertH;
        public float width;
    }


    // add menu
    [MenuItem("工具菜单/美术/生成字体")]
    static void Init()
    {
        EditorWindow.GetWindow(typeof(BMFontEditor));

    }

    void OnGUI()
    {
        EditorGUILayout.BeginVertical();

        fontTexture = (Texture)EditorGUILayout.ObjectField("Font Texture(Sprite格式)", fontTexture, typeof(Texture), false);

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("Use BMFont fnt File", EditorStyles.boldLabel);
        EditorGUILayout.LabelField("(must Font Descriptor select Text)", EditorStyles.boldLabel);

        fontPosTbl = (TextAsset)EditorGUILayout.ObjectField("BMFont fnt (.fnt)", fontPosTbl, typeof(TextAsset), false);
        if (GUILayout.Button("Create"))
        {

            if (fontTexture == null) this.ShowNotification(new GUIContent("No Font Texture selected"));
            else if (fontPosTbl == null) this.ShowNotification(new GUIContent("No Font Position Table file selected"));
            else
            {
                CalcChrRect(fontPosTbl, fontTexture);
            }
        }
        EditorGUILayout.LabelField("输出路径在.fnt文件的同级目录", EditorStyles.largeLabel);
        EditorGUILayout.EndVertical();
    }

    void OnInspectorUpdate()
    {
        this.Repaint();
    }


    void CalcChrRect(TextAsset posTbl, Texture tex)
    {
        string fileName = AssetDatabase.GetAssetPath(fontPosTbl);
        string texName = AssetDatabase.GetAssetPath(tex);
        string fontName = System.IO.Path.GetFileNameWithoutExtension(fileName);
        string fontPath = fileName.Replace(".fnt", ".fontsettings");
        string matPath = fileName.Replace(".fnt", ".mat");
        float imgw = (float)tex.width;
        float imgh = (float)tex.height;
        string txt = posTbl.text;

        List<ChrRect> tblList = new List<ChrRect>();
        foreach (string line in txt.Split('\n'))
        {
            if (line.IndexOf("char id=") == 0)
            {
                ChrRect d = GetChrRect(line, imgw, imgh);
                tblList.Add(d);
            }
        }
        if (tblList.Count == 0)
        {
            new GUIContent("Failed");
            return;
        }

        ChrRect[] tbls = tblList.ToArray();
        Font font = new Font();
        font.name = fontName;
        SetCharacterInfo(tbls, font);


        Material mat = new Material(Shader.Find("Unlit/Transparent"));
        mat.mainTexture = tex;
        mat.name = fontName;
        font.material = mat;


        Debug.Log(System.IO.Path.GetFileNameWithoutExtension(fileName));
        Debug.Log(fileName);

        AssetDatabase.CreateAsset(mat, matPath);
        AssetDatabase.CreateAsset(font, fontPath);
        AssetDatabase.SaveAssets();
        this.ShowNotification(new GUIContent("Complete"));
        AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    }

    void SetCharacterInfo(ChrRect[] tbls, Font fontObj)
    {
        CharacterInfo[] nci = new CharacterInfo[tbls.Length];
        for (int i = 0; i < tbls.Length; i++)
        {
            nci[i].index = tbls[i].index;
            nci[i].advance = (int)tbls[i].width;
            nci[i].uv.x = tbls[i].uvX;
            nci[i].uv.y = tbls[i].uvY;
            nci[i].uv.width = tbls[i].uvW;
            nci[i].uv.height = tbls[i].uvH;
            nci[i].vert.x = tbls[i].vertX;
            nci[i].vert.y = tbls[i].vertY;
            nci[i].vert.width = tbls[i].vertW;
            nci[i].vert.height = tbls[i].vertH;
        }
        fontObj.characterInfo = nci;
    }

    ChrRect GetChrRect(string line, float imgw, float imgh)
    {
        ChrRect d = new ChrRect();

        foreach (string s in line.Split(' '))
        {
            if (s.IndexOf("id=") >= 0) d.id = GetParamInt(s, "id=");
            else if (s.IndexOf("x=") >= 0) d.x = GetParamInt(s, "x=");
            else if (s.IndexOf("y=") >= 0) d.y = GetParamInt(s, "y=");
            else if (s.IndexOf("width=") >= 0) d.w = GetParamInt(s, "width=");
            else if (s.IndexOf("height=") >= 0) d.h = GetParamInt(s, "height=");
            else if (s.IndexOf("xoffset=") >= 0) d.xofs = GetParamInt(s, "xoffset=");
            else if (s.IndexOf("yoffset=") >= 0) d.yofs = GetParamInt(s, "yoffset=");
            else if (s.IndexOf("xadvance=") >= 0) d.width = GetParamInt(s, "xadvance=");
        }
        d.index = d.id;
        d.uvX = (float)d.x / imgw;
        d.uvY = (float)(imgh - (d.y)) / imgh;
        d.uvW = (float)d.w / imgw;
        //d.uvH = (float)-d.h / imgh;
        d.uvH = (float)-d.h / imgh;

        d.vertX = (float)d.xofs;
        d.vertY = (float)d.yofs;
        d.vertW = d.w;
        d.vertH = d.h;

        return d;
    }

    int GetParamInt(string s, string wd)
    {
        if (s.IndexOf(wd) >= 0)
        {
            int v;
            if (int.TryParse(s.Substring(wd.Length), out v)) return v;
        }
        return int.MaxValue;
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值