找回密码
 立即注册
查看: 371|回复: 0

在Unity中,制作自定义字体

[复制链接]
发表于 2022-4-28 14:32 | 显示全部楼层 |阅读模式
参考

Unity UGUI 数字使用图片显示-BMFont
Unity / custom font自定义字体
说明

游戏中的数字(尤其是头顶飘血等),有时需要使用比较个性化的风格。
可以使用图片(其中包含对应的字)生成字体。
步骤

1 制作图片


图片中包含所有想要的字。
每个字占用的区域范围最好是相同的,以方便在Unity中切割成小图。


image.png

2 将图片按字切分成若干小图


在Unity中

    通过SpriteEditor将原图拆成小图


    image.png


    选中原图,Tools->SplitTexture


    image.png

    可在与原图同目录下生成同名目录,在其中将前述小图分别生成独立的png。


    image.png

3 借助bmfont,将前面做好的小图转成fnt和png


bmfont下载地址
打开bmfont64.exe,获知 0~9 的Id是 48~57。
Edit->Open Image Manager,在打开的Image Manager中点击Image -> Import Image...
导入图片“0”,将Id填为48.


image.png

关闭Bitmap font generator,可看到在bmfont64.exe同目录下生成文件bmfont.bmfc。


image.png

用文本编辑器打开这个文件,在它的底端可看到前面载入的图片信息,将其余图片的信息填入,保存。


image.png


image.png

再次打开bmfont64.exe,打开Image Manager确认通过前述直接修改文件的方式成功载入了其他图片。


image.png

Options -> Export options,按下图进行设置。


image.png

Options -> Save bitmap font as : 生成一个fnt文件和一个png文件。


image.png

4 在Unity中,将fnt和png转成字体


将前一步得到的fnt和png放入Unity工程中。
Unity菜单栏:BitmapFontExporter->Create:将这2个文件拖入工具,生成字体。


image.png

可以微调各字符的Advance(字符宽度)来控制相邻两字符的间距。


image.png

5 在Unity中做好的字体的显示效果


image.png

工具


image.png

BitmapFontExporter


用法:BitmapFontExporter->Create,将通过bmfont生成的fnt和png拖入,点击Create,生成fontsettings和mat。
using UnityEngine;using UnityEditor;using System.IO;using System.Xml;using System;public class BitmapFontExporter : ScriptableWizard{    [MenuItem("BitmapFontExporter/Create")]    private static void CreateFont()    {        ScriptableWizard.DisplayWizard<BitmapFontExporter>("Create Font");    }    public TextAsset fontFile;    public Texture2D textureFile;    private void OnWizardCreate()    {        if (fontFile == null || textureFile == null)        {            return;        }        string path = EditorUtility.SaveFilePanelInProject("Save Font", fontFile.name, "", "");        if (!string.IsNullOrEmpty(path))        {            ResolveFont(path);        }    }    private void ResolveFont(string exportPath)    {        if (!fontFile) throw new UnityException(fontFile.name + "is not a valid font-xml file");        Font font = new Font();        XmlDocument xml = new XmlDocument();        xml.LoadXml(fontFile.text);        XmlNode info = xml.GetElementsByTagName("info")[0];        XmlNodeList chars = xml.GetElementsByTagName("chars")[0].ChildNodes;        CharacterInfo[] charInfos = new CharacterInfo[chars.Count];        for (int cnt = 0; cnt < chars.Count; cnt++)        {            XmlNode node = chars[cnt];            CharacterInfo charInfo = new CharacterInfo();            charInfo.index = ToInt(node, "id");            charInfo.width = ToInt(node, "xadvance");            charInfo.uv = GetUV(node);            charInfo.vert = GetVert(node);            charInfos[cnt] = charInfo;        }        Shader shader = Shader.Find("Unlit/Transparent");        Material material = new Material(shader);        material.mainTexture = textureFile;        AssetDatabase.CreateAsset(material, exportPath + ".mat");        font.material = material;        font.name = info.Attributes.GetNamedItem("face").InnerText;        font.characterInfo = charInfos;        AssetDatabase.CreateAsset(font, exportPath + ".fontsettings");    }    private Rect GetUV(XmlNode node)    {        Rect uv = new Rect();        uv.x = ToFloat(node, "x") / textureFile.width;        uv.y = ToFloat(node, "y") / textureFile.height;        uv.width = ToFloat(node, "width") / textureFile.width;        uv.height = ToFloat(node, "height") / textureFile.height;        uv.y = 1f - uv.y - uv.height;        return uv;    }    private Rect GetVert(XmlNode node)    {        Rect uv = new Rect();        uv.x = ToFloat(node, "xoffset");        uv.y = ToFloat(node, "yoffset");        uv.width = ToFloat(node, "width");        uv.height = ToFloat(node, "height");        uv.y = -uv.y;        uv.height = -uv.height;        return uv;    }    private int ToInt(XmlNode node, string name)    {        return Convert.ToInt32(node.Attributes.GetNamedItem(name).InnerText);    }    private float ToFloat(XmlNode node, string name)    {        return (float)ToInt(node, name);    }}SplitTexture


用法:在Project中选定一张图,Tools->SplitTexture
// SplitTexture.csusing UnityEngine;using UnityEditor;using System.IO;/// <summary>/// 将图片分离成多张小图/// </summary>public class SplitTexture{    [MenuItem("Tools/SplitTexture")]    static void DoSplitTexture()    {        // 获取所选图片        Texture2D selectedImg = Selection.activeObject as Texture2D;        string rootPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(selectedImg));        string path = rootPath + "/" + selectedImg.name + ".png";        TextureImporter texImp = AssetImporter.GetAtPath(path) as TextureImporter;        // 设置为可读        texImp.isReadable = true;        AssetDatabase.ImportAsset(path);        // 创建文件夹        AssetDatabase.CreateFolder(rootPath, selectedImg.name);        foreach (SpriteMetaData metaData in texImp.spritesheet)        {            var width = (int)metaData.rect.width;            var height = (int)metaData.rect.height;            Texture2D smallImg = new Texture2D(width, height);            var pixelStartX = (int)metaData.rect.x;            var pixelEndX = pixelStartX + width;            var pixelStartY = (int)metaData.rect.y;            var pixelEndY = pixelStartY + height;            for (int x = pixelStartX; x <= pixelEndX; ++x)            {                for (int y = pixelStartY; y <= pixelEndY; ++y)                {                    smallImg.SetPixel(x - pixelStartX, y - pixelStartY, selectedImg.GetPixel(x, y));                }            }            //  转换纹理到EncodeToPNG兼容格式            if (TextureFormat.ARGB32 != smallImg.format  && TextureFormat.RGB24 != smallImg.format)            {                Texture2D img = new Texture2D(smallImg.width, smallImg.height);                img.SetPixels(smallImg.GetPixels(0), 0);                smallImg = img;            }            // 保存小图文件            string smallImgPath = rootPath + "/" + selectedImg.name + "/" + metaData.name + ".png";            File.WriteAllBytes(smallImgPath, smallImg.EncodeToPNG());            // 刷新资源窗口界面            AssetDatabase.Refresh();            // 设置小图的格式            TextureImporter smallTextureImp = AssetImporter.GetAtPath(smallImgPath) as TextureImporter;            // 设置为可读            smallTextureImp.isReadable = true;            // 设置alpha通道            smallTextureImp.alphaIsTransparency = true;            // 不开启mipmap            smallTextureImp.mipmapEnabled = false;            AssetDatabase.ImportAsset(smallImgPath);        }    }}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 13:38 , Processed in 0.067015 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表