美文网首页
在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中,制作自定义字体

    参考 Unity UGUI 数字使用图片显示-BMFont[https://zhuanlan.zhihu.com/...

  • 使用全景图制作天空盒

    记录环境:unity 5.6 在Unity中使用全景图制作天空盒,可以在不使用模型的情况下制作出自定义的大环境。 ...

  • UGUI自定义字体

    Babybus-u3d技术交流-UGUI自定义字体 UGUI的自定义字体为 并且官方没有提供相对应的字体制作工具。...

  • Unity查找哪些Label引用了Unity自带的字体

    Unity中的Label控件引用了Unity自带字体的话,打包时会报错,所以得找出来把这些字体都改成动态字体。 u...

  • iOS在应用中添加自定义字体

    iOS在应用中添加自定义字体 一、在应用中添加自定义字体的步骤 1、网上提供的字体库有很多,下载完成后,将其导入工...

  • Unity 动画系列一 属性动画 序列帧动画

    参考Unity动画系统详解1:在Unity中如何制作动画?[https://zhuanlan.zhihu.com/...

  • 18072509 动画系统

    0725视频 9 动画系统 人物移动控制 - Unity动画系统 来源 -建模中制作 unity内制作 实例 移动...

  • 用Animation制作坦克动画

    题目在Unity中制作一个坦克模型,实现动画:前进,停止,发射子弹 制作思路制作坦克模型制作坦克动画 制作步骤制作...

  • Swift自定义字体

    将所用到的字体导入工程Bundle中 在Plist文件中添加以下key和使用到的字体名称 在代码中使用自定义字体

  • Unity UGUI实现图文混排

    目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英...

网友评论

      本文标题:在Unity中,制作自定义字体

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