UGUI使用BMFont制作美術字體<一>


不多說,先來效果圖:

從頭開始講開發流程:

在Unity3d開發過程中,經常需要將美術提供的美術字組合成一個字體庫,方便unity中的調用,BMFont則為此提供了不錯的功能支持,它的下載地址在這里。它的使用方法網上有很多教程,這里不做解釋,如果要使用此工具,要注意的是,這里記得使用xml格式,導出的圖片為一張。

導出來的資源有:對應的圖片,還有一個以fnt結尾的文件,如果打開此文件可以看到它就是一個xml文件:

在BMFont軟件中我們這樣操作:Options->Save configuration as...,把這個文件保存下來,它是以bmfc結尾的,保存了在bmfont里面相關的配置屬性,其中對應的文字圖片還有對應的值在imported icon images中保存,用記事本打開,就可以可到這樣的界面:

以我的直覺,BMFont就是根據這樣的一個配置文件生成對應的圖片和xml文件。現在回到Unity,將BMFont生成的xml和圖片分別拖動到1,2位置,點擊Generate Font在對應的xml目錄下便會生成字體文件和材質球,並且分別已經賦值,將字體拖動到ugui中的字體位置可見:

這樣一個工具算是完成了,它的代碼在這里,自己也可以進行修改。但是作為懶癌的我,覺得這樣極不方便,制作字體時候,每次都要打開bmfont,然后導入unity,再接着將文件拖動到相關位置,還要點擊生成字體,簡直不能忍受,那么下一篇我們制作一個更加方便的工具。

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

public class BMFont : EditorWindow
{
    private TextAsset _fontTextAsset;
    private Texture _fontTexture;
    private string _fontsDir;

    [MenuItem("CTools/BMFont", false, 12)]
    private static void BMFontTools()
    {
        BMFont bmFont = new BMFont();
        bmFont.Show();
    }

    private string _getAssetPath(string path)
    {
        string pathTemp = path.Replace("\\", "/");
        pathTemp = pathTemp.Replace(Application.dataPath, "Assets");
        return pathTemp;
    }

    void OnGUI()
    {
        EditorGUILayout.BeginVertical();
        TextAsset taTemp = EditorGUILayout.ObjectField("選擇Font文件:", _fontTextAsset, typeof(TextAsset), true) as TextAsset;
        if (taTemp != _fontTextAsset && taTemp != null)
        {
            string assetDir = Directory.GetParent(AssetDatabase.GetAssetPath(taTemp)).FullName;
            assetDir = _getAssetPath(assetDir);
            string imgPath = string.Format("{0}/{1}_0.png", assetDir, taTemp.name);
            _fontTexture = AssetDatabase.LoadAssetAtPath<Texture>(imgPath);
            _fontsDir = string.Format("{0}.fontsettings", Path.Combine(assetDir, taTemp.name));
            if (_fontTexture == null)
            {
                _fontsDir = string.Empty;
                Debug.LogError(string.Format("未發現{0}文件", imgPath));
            }
        }
        _fontTextAsset = taTemp;

        _fontTexture = EditorGUILayout.ObjectField("選擇Font圖片文件:", _fontTexture, typeof(Texture), true) as Texture;

        GUI.enabled = false;
        _fontsDir = EditorGUILayout.TextField("字體生成路徑:", _fontsDir);
        GUI.enabled = true;
        if (GUILayout.Button("Generate Font"))
        {
            if (!string.IsNullOrEmpty(_fontsDir))
            {
                Material mat = AssetDatabase.LoadAssetAtPath<Material>(_fontsDir.Replace(".fontsettings", ".mat"));
                if (mat == null)
                {
                    mat = new Material(Shader.Find("UI/Default Font"));
                    AssetDatabase.CreateAsset(mat, _fontsDir.Replace(".fontsettings", ".mat"));
                }
                if (_fontTexture != null)
                {
                    mat = AssetDatabase.LoadAssetAtPath<Material>(_fontsDir.Replace(".fontsettings", ".mat"));
                    mat.SetTexture("_MainTex", _fontTexture);
                }
                else
                {
                    Debug.LogError("貼圖未做配置,請檢查配置");
                    return;
                }

                Font font = AssetDatabase.LoadAssetAtPath<Font>(_fontsDir);
                if (font == null)
                {
                    font = new Font();
                    AssetDatabase.CreateAsset(font, _fontsDir);
                }

                _setFontInfo(AssetDatabase.LoadAssetAtPath<Font>(_fontsDir),
                    AssetDatabase.GetAssetPath(_fontTextAsset),
                    _fontTexture);
                font = AssetDatabase.LoadAssetAtPath<Font>(_fontsDir);
                font.material = mat;
            }
            else
            {
                Debug.LogError("創建失敗,請檢查配置");
            }
        }
        EditorGUILayout.EndVertical();
    }

    private void _setFontInfo(Font font, string fontConfig, Texture texture)
    {
        XmlDocument xml = new XmlDocument();
        xml.Load(fontConfig);
        List<CharacterInfo> chtInfoList = new List<CharacterInfo>();
        XmlNode node = xml.SelectSingleNode("font/chars");
        foreach (XmlNode nd in node.ChildNodes)
        {
            XmlElement xe = (XmlElement)nd;
            int x = int.Parse(xe.GetAttribute("x"));
            int y = int.Parse(xe.GetAttribute("y"));
            int width = int.Parse(xe.GetAttribute("width"));
            int height = int.Parse(xe.GetAttribute("height"));
            int advance = int.Parse(xe.GetAttribute("xadvance"));
            CharacterInfo info = new CharacterInfo();
            info.glyphHeight = texture.height;
            info.glyphWidth = texture.width;
            info.index = int.Parse(xe.GetAttribute("id"));
            //這里注意下UV坐標系和從BMFont里得到的信息的坐標系是不一樣的哦,前者左下角為(0,0),
            //右上角為(1,1)。而后者則是左上角上角為(0,0),右下角為(圖寬,圖高)
            info.uvTopLeft = new Vector2((float)x / texture.width, 1 - (float)y / texture.height);
            info.uvTopRight = new Vector2((float)(x + width) / texture.width, 1 - (float)y / texture.height);
            info.uvBottomLeft = new Vector2((float)x / texture.width, 1 - (float)(y + height) / texture.height);
            info.uvBottomRight = new Vector2((float)(x + width) / texture.width, 1 - (float)(y + height) / texture.height);

            info.minX = 0;
            info.minY = -height;
            info.maxX = width;
            info.maxY = 0;

            info.advance = advance;

            chtInfoList.Add(info);
        }
        font.characterInfo = chtInfoList.ToArray();
        AssetDatabase.Refresh();
    }
}

 

參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM