美文网首页
在Unity中,制作自定义字体

在Unity中,制作自定义字体

作者: 全新的饭 | 来源:发表于2022-04-28 11:48 被阅读0次

    参考

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

    说明

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

    步骤

    1 制作图片

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


    image.png

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

    在Unity中

    1. 通过SpriteEditor将原图拆成小图


      image.png
    2. 选中原图,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.cs
    
    using 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中,制作自定义字体

          本文链接:https://www.haomeiwen.com/subject/hxtdyrtx.html