fnt文件生成unity字体的原理其实就是渲染图集Atlas上的Sprite,这边直接利用Unity自带的图集工具生成fnt文件
注意:这里生成的fnt文件还没发直接用,因为没有关联字符,这个工具只是第1步,要配合Fnt编辑工具一起使用
public class SpriteToFntTool : EditorWindow { [MenuItem("MyTools/Sprite To Fnt", false, 100)] private static void ShowWindow() { var wnd = GetWindow<SpriteToFntTool>(false, "SpriteToFnt"); } private Vector2 m_ScrollPos = new Vector2(0, 0); private GUIContent m_TempLabelContent = new GUIContent(); private Sprite m_Sprite; private void OnGUI() { GUILayout.Space(6); float labelWidthBak = EditorGUIUtility.labelWidth; if (null == m_Sprite) EditorGUILayout.HelpBox($"请先选择一个设置了Packing Tag的Sprite", MessageType.Warning); EditorGUILayout.BeginHorizontal(); m_TempLabelContent.text = "Sprite: "; EditorGUIUtility.labelWidth = GUI.skin.label.CalcSize(m_TempLabelContent).x + 2; EditorGUILayout.PrefixLabel("Sprite:"); m_Sprite = EditorGUILayout.ObjectField(m_Sprite, typeof(Sprite), false) as Sprite; EditorGUILayout.EndHorizontal(); if (null != m_Sprite) { if (GUILayout.Button("刷新Packer图集")) { EditorUtility.DisplayProgressBar("RebuildAtlasCacheIfNeeded...", "RebuildAtlasCacheIfNeeded...", 0); Packer.RebuildAtlasCacheIfNeeded(EditorUserBuildSettings.activeBuildTarget, true, Packer.Execution.ForceRegroup); EditorUtility.ClearProgressBar(); } Packer.GetAtlasDataForSprite(m_Sprite, out var packTag, out var atlasTex); var spFilePath = AssetDatabase.GetAssetPath(m_Sprite); var spFolderPath = Path.GetDirectoryName(spFilePath); if (null != atlasTex) { EditorGUILayout.LabelField($"所选Sprite的Packing Tag: {packTag}"); EditorGUILayout.LabelField($"Sprite所在文件夹:{spFolderPath}"); EditorGUILayout.LabelField("图集贴图:"); GUILayout.Label(atlasTex, GUILayout.MaxHeight(120)); GUILayout.Space(10); if (!EditorApplication.isPlaying) { EditorGUILayout.HelpBox("请先运行Editor, 非运行状态无法获取到Packer图集的精灵信息", MessageType.Warning); GUI.enabled = false; } EditorGUILayout.BeginHorizontal(); if (GUILayout.Button($" 生成{packTag}.fnt ")) { CreateFntFile(packTag, atlasTex, spFolderPath); } GUI.enabled = true; GUILayout.Space(10); if (GUILayout.Button($" 生成{packTag}.png ")) { var pngFileName = $"{packTag}.png"; var pngFilePath = Path.Combine(spFolderPath, pngFileName); ExportTexture(pngFilePath, atlasTex); AssetDatabase.ImportAsset(pngFilePath); //不存在则不需要导入 AssetDatabase.Refresh(); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); } } EditorGUIUtility.labelWidth = labelWidthBak; GUILayout.Space(6); } private static void CreateFntFile(string packingTag, Texture2D fntTex, string spFolderPath) { var fntFilePath = Path.Combine(spFolderPath, $"{packingTag}.fnt"); if (File.Exists(fntFilePath)) { if (!EditorUtility.DisplayDialog("文件已存在", $"是否覆盖{fntFilePath}?", "Yes", "No")) return; } Fnt fnt = new Fnt(); fnt.texWidth = fntTex.width; fnt.texHeight = fntTex.height; fnt.file = $"{packingTag}.png"; var pngFiles = Directory.GetFiles(spFolderPath, "*.png", SearchOption.TopDirectoryOnly); int charCnt = 0; int maxHeight = 0; foreach (var pngFile in pngFiles) { var pngIMP = AssetImporter.GetAtPath(pngFile) as TextureImporter; if (pngIMP.spritePackingTag != packingTag) continue; var sp = AssetDatabase.LoadAssetAtPath<Sprite>(pngFile); FntChar fntChar = new FntChar(); fnt.charsList.Add(fntChar); var texRect = sp.textureRect; fntChar.w = (int)texRect.width; fntChar.h = (int)texRect.height; fntChar.x = (int)texRect.x; fntChar.y = fntTex.height - (int)texRect.y - fntChar.h; //fnt中的x, y为左上角, 以贴图左上角为(0, 0) maxHeight = Mathf.Max(maxHeight, fntChar.h); fntChar.xadv = fntChar.w; charCnt++; } fnt.fontSize = maxHeight; fnt.lineHeight = maxHeight; fnt.baseLine = (int)(maxHeight * 0.9f); using (StreamWriter sw = new StreamWriter(fntFilePath, false, Encoding.UTF8)) { sw.WriteLine($"info face=\"Art\" size={fnt.fontSize}"); sw.WriteLine($"common lineHeight={fnt.lineHeight} base={fnt.baseLine} scaleW={fnt.texWidth} scaleH={fnt.texHeight} pages=1"); sw.WriteLine($"page id=0 file=\"{fnt.file}\""); sw.WriteLine($"chars count={fnt.charsList.Count}"); foreach (var c in fnt.charsList) { sw.WriteLine($"char id={c.id} x={c.x} y={c.y} width={c.w} height={c.h} xoffset={c.xoff} yoffset={c.yoff} xadvance={c.xadv}"); } } AssetDatabase.ImportAsset(fntFilePath); AssetDatabase.Refresh(); } static void ExportTexture(string outFilePath, Texture tex) { var tempRT = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32); Graphics.SetRenderTarget(tempRT); Graphics.Blit(tex, tempRT); var resultTex = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false); resultTex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0); resultTex.Apply(); var bytes = resultTex.EncodeToPNG(); Graphics.SetRenderTarget(null); RenderTexture.ReleaseTemporary(tempRT); File.WriteAllBytes(outFilePath, bytes); } }
public class Fnt { public int fontSize = 22; //字体大小 public int lineHeight = 22; //行高 public int baseLine = 20; //基线位置 public int texWidth = 512; //贴图宽度 public int texHeight = 256; //贴图高度 public string file = ""; //贴图名字 public List<FntChar> charsList = new List<FntChar>(); } public class FntChar { public string ch = ""; //对应字符 //unicode码 public int id; //在贴图上的坐标(左上角), 相对贴图左上角 public int x; public int y; //在贴图上的宽高 public int w; public int h; //排版修正 public int xoff; public int yoff; //排版宽度 public int xadv; }
标签:Fnt,Sprite,int,var,fnt,Atlas,EditorGUILayout,public,图集 From: https://www.cnblogs.com/sailJs/p/18166751