using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; // 创建bmfont namespace FL.Editor { public class BMFontCreator { [MenuItem("Assets/Create/XGame/CreateBMFont")] static void Create() { var creator = new BMFontCreator(); creator.Start(); } private void Start() { var obj = Selection.activeObject; string fntPath = AssetDatabase.GetAssetPath(obj); if (fntPath.IndexOf(".fnt") == -1) { // 不是字体文件 Debug.LogError("请先选择一个*.fnt!"); return; } //if (!File.Exists(customFontPath)) //{ // Debug.LogError("The .fontsettings file not exists"); // return; //} Debug.Log(fntPath); using var reader = new StreamReader(new FileStream(fntPath, FileMode.Open)); var charInfos = new List(); var reg = new Regex(@"char id=(?\d+)\s+x=(?\d+)\s+y=(?\d+)\s+width=(?\d+)\s+height=(?\d+)\s+xoffset=(?(-|\d)+)\s+yoffset=(?(-|\d)+)\s+xadvance=(?\d+)\s+"); string line = reader.ReadLine(); int lineHeight = 65; int texWidth = 512; int texHeight = 512; var pngName = ""; while (line != null) { if (line.IndexOf("char id=") != -1) { var match = reg.Match(line); if (match.Success) { var id = System.Convert.ToInt32(match.Groups["id"].Value); var x = System.Convert.ToInt32(match.Groups["x"].Value); var y = System.Convert.ToInt32(match.Groups["y"].Value); var width = System.Convert.ToInt32(match.Groups["width"].Value); var height = System.Convert.ToInt32(match.Groups["height"].Value); var xoffset = System.Convert.ToInt32(match.Groups["xoffset"].Value); var yoffset = System.Convert.ToInt32(match.Groups["yoffset"].Value); var xadvance = System.Convert.ToInt32(match.Groups["xadvance"].Value); Debug.Log($"字符:{(char)id} id:{id} width:{width} height:{height}"); if (height > lineHeight) lineHeight = height; var info = new CharacterInfo { index = id }; //uv左下角(0,0)->右上角(1,1) float uvx = 1f * x / texWidth; float uvy = 1 - (1f * y / texHeight); float uvw = 1f * width / texWidth; float uvh = 1f * height / texHeight; info.uvBottomLeft = new Vector2(uvx, uvy - uvh); info.uvBottomRight = new Vector2(uvx + uvw, uvy - uvh); info.uvTopLeft = new Vector2(uvx, uvy); info.uvTopRight = new Vector2(uvx + uvw, uvy); info.minX = xoffset; //glyphHeight赋值时内部会加上高度,需要提前减掉高度 //文本上对齐时: - height,居中对其时: - height / 2 //下对齐时不用减 info.minY = yoffset - height / 2; info.glyphWidth = width; info.glyphHeight = height; info.advance = xadvance; //info.size = 18; //info.style = FontStyle.Italic; charInfos.Add(info); } } else if (line.IndexOf("scaleW=") != -1) { var reg2 = new Regex(@"common lineHeight=(?\d+)\s+.*scaleW=(?\d+)\s+scaleH=(?\d+)"); var match = reg2.Match(line); if (match.Success) { lineHeight = System.Convert.ToInt32(match.Groups["lineHeight"].Value); texWidth = System.Convert.ToInt32(match.Groups["scaleW"].Value); texHeight = System.Convert.ToInt32(match.Groups["scaleH"].Value); } } else if (line.IndexOf("file=") != -1) { var match = Regex.Match(line, @"\s+.*file=""(.+?)"""); if (match.Success) { pngName = match.Groups[1].Value; } } line = reader.ReadLine(); } Debug.Log($"字体贴图 Name:{pngName} Width:{texWidth} Height:{texHeight} "); if (string.IsNullOrEmpty(pngName)) { Debug.LogError($"字体贴图名字为空, 请检查*.fnt文件."); return; } var texturePath = Path.Combine(Path.GetDirectoryName(fntPath), pngName); var texture = AssetDatabase.LoadAssetAtPath(texturePath); if (texture == null) { Debug.LogError($"找不到字体贴图. Path:{texturePath}"); return; } var customFontPath = fntPath.Replace(".fnt", ".fontsettings"); var customFont = AssetDatabase.LoadAssetAtPath(customFontPath); if (customFont == null) { customFont = new Font(Path.GetFileNameWithoutExtension(fntPath)); AssetDatabase.CreateAsset(customFont, customFontPath); } var matiralPath = fntPath.Replace(".fnt", ".mat"); var material = AssetDatabase.LoadAssetAtPath(matiralPath); if (material == null) { material = new Material(Shader.Find("XGame/Text Shader")); AssetDatabase.CreateAsset(material, matiralPath); } material.mainTexture = texture; customFont.material = material; customFont.characterInfo = charInfos.ToArray(); EditorUtility.SetDirty(material); EditorUtility.SetDirty(customFont); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); if (customFont.lineHeight < lineHeight) { Debug.LogWarning($"需要手动修改字体的LineSpacing. 当前:{customFont.lineHeight} 推荐:{lineHeight}"); } Debug.Log($"字体生成完成. Path:{customFontPath}"); } } }