很少說,先來效果圖:node
從頭開始講開發流程:工具
在Unity3d開發過程當中,常常須要將美術提供的美術字組合成一個字體庫,方便unity中的調用,BMFont則爲此提供了不錯的功能支持,它的下載地址在這裏。它的使用方法網上有不少教程,這裏不作解釋,若是要使用此工具,要注意的是,這裏記得使用xml格式,導出的圖片爲一張。字體
導出來的資源有:對應的圖片,還有一個以fnt結尾的文件,若是打開此文件能夠看到它就是一個xml文件:ui
在BMFont軟件中咱們這樣操做:Options->Save configuration as...,把這個文件保存下來,它是以bmfc結尾的,保存了在bmfont裏面相關的配置屬性,其中對應的文字圖片還有對應的值在imported icon images中保存,用記事本打開,就能夠可到這樣的界面:spa
以個人直覺,BMFont就是根據這樣的一個配置文件生成對應的圖片和xml文件。如今回到Unity,將BMFont生成的xml和圖片分別拖動到1,2位置,點擊Generate Font在對應的xml目錄下便會生成字體文件和材質球,而且分別已經賦值,將字體拖動到ugui中的字體位置可見:.net
這樣一個工具算是完成了,它的代碼在這裏,本身也能夠進行修改。可是做爲懶癌的我,以爲這樣極不方便,製做字體時候,每次都要打開bmfont,而後導入unity,再接着將文件拖動到相關位置,還要點擊生成字體,簡直不能忍受,那麼下一篇咱們製做一個更加方便的工具。3d
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(); } }
參考:code