Unity Custom Font 创建图片字体

参考文章

详细步骤说明

  1. 新的字体图片BattleTextFont.png,放置于Resources目录下,如图
    字体图片
  2. 选中图片,将Sprite Mode设置为Multiple
    在这里插入图片描述
  3. 点击Sprite Editor 将各个字切割好
  4. 创建工具脚本CostomFont.cs,自动生成字体文件,右键菜单会出现CreateMyFontSprite选项
using UnityEngine;
using UnityEditor;
using System.IO;
 
public class CustomFont : MonoBehaviour
{
    //本方法是通过裁切的sprite导出字体文件,裁切使用的是unity自带的sprite editor,方便操作。
    //另外,裁切之后,每个sprite的名字的最后一个字符对应了ascii码的编码,比如:
    //0: 我们只要将sprite的名字命名成xxx0,就可以了!
    //由于使用到的了sprite加载,所以字体图片请放在Resources目录下面,等制作完毕,再把他们放到fonts文件夹或者其他文件夹中即可。
    [MenuItem("Assets/CreateMyFontSprite")]
    static void CreateMyFontSprite()
    {

        Debug.LogWarning("abc");

        if (Selection.objects == null)
        {
            Debug.LogWarning("没有选中Sprite文件,需要将Sprite Mode设置成Multiple,切分好,并且以以名字的最后一个字符当做ascii码111");
            return;
        }
        if (Selection.objects.Length == 0)
        {
            Debug.LogWarning("没有选中Sprite文件,需要将Sprite Mode设置成Multiple,切分好,并且以以名字的最后一个字符当做ascii码");
            return;
        }
        string resoursePath = "Resources";
        UnityEngine.Object o = Selection.objects[0];
        if (o.GetType() != typeof(Texture2D))
        {
            Debug.LogWarning("选中的并不是图片文件");
            return;
        }
        string selectionPath = AssetDatabase.GetAssetPath(o);
        Debug.Log("selectionPath=" + selectionPath);
        //if (selectionPath.Contains(resoursePath))
        {
            string selectionExt = Path.GetExtension(selectionPath);
            if (selectionExt.Length == 0)
            {
                Debug.LogWarning("选中的扩展名是为空");
                return;
            }
            string loadPath = selectionPath.Remove(selectionPath.Length - selectionExt.Length);
            string fontPathName = loadPath + ".fontsettings";
            string matPathName = loadPath + ".mat";
            float lineSpace = 0.1f;//字体行间距,下面会根据最高的字体得到行间距,如果是固定高度,可以在这里自行调整  
            loadPath = Path.GetFileNameWithoutExtension(selectionPath);
            Sprite[] sprites = Resources.LoadAll<Sprite>(loadPath);
            Debug.Log("loadPath=" + loadPath + ",size=" + sprites.Length);
            if (sprites.Length > 0)
            {
                //以textrue方式获得该资源,可以设置到创建的材质中去  
                Texture2D tex = o as Texture2D;
                //创建字体材质,并且将图片设置好  
                Material mat = new Material(Shader.Find("GUI/Text Shader"));
                AssetDatabase.CreateAsset(mat, matPathName);
                mat.SetTexture("_MainTex", tex);
                //创建字体文件,设置字体文件的材质  
                Font m_myFont = new Font();
                m_myFont.material = mat;
                AssetDatabase.CreateAsset(m_myFont, fontPathName);
                //创建字体中的字符集数组  
                CharacterInfo[] characterInfo = new CharacterInfo[sprites.Length];
                bool[] flags = new bool[sprites.Length];
                //得到最高的高度,设置行高和进行偏移计算  
                for (int i = 0; i < sprites.Length; i++)
                {
                    if (sprites[i].rect.height > lineSpace)
                    {
                        lineSpace = sprites[i].rect.height;
                    }
                }
                int realIndex = 0;
                for (int i = 0; i < sprites.Length; i++)
                {
                    Sprite spr = sprites[i];
                    if (!spr.name.StartsWith("font_"))
                    {
                        Debug.Log("skip sprite " + spr.name + ", the name doesn't starts with font_");
                        flags[i] = false;
                    }
                    else
                    {
                        flags[i] = true;
                        realIndex++;
                    }
                    CharacterInfo info = new CharacterInfo();
                    //设置ascii码,使用切分sprite的最后一个字母  
                    info.index = (int)spr.name[spr.name.Length - 1];
                    Rect rect = spr.rect;
                    //根据pivot设置字符的偏移,具体需要做成什么样的,可以根据自己需要修改公式  
                    float pivot = spr.pivot.y / rect.height - 0.5f;
                    if (pivot > 0)
                    {
                        pivot = -lineSpace / 2 - spr.pivot.y;
                    }
                    else if (pivot < 0)
                    {
                        pivot = -lineSpace / 2 + rect.height - spr.pivot.y;
                    }
                    else
                    {
                        pivot = -lineSpace / 2;
                    }
                    Debug.Log(pivot);
                    int offsetY = (int)(pivot + (lineSpace - rect.height) / 2);
                    //设置字符映射到材质上的坐标  
                    info.uvBottomLeft = new Vector2((float)rect.x / tex.width, (float)(rect.y) / tex.height);
                    info.uvBottomRight = new Vector2((float)(rect.x + rect.width) / tex.width, (float)(rect.y) / tex.height);
                    info.uvTopLeft = new Vector2((float)rect.x / tex.width, (float)(rect.y + rect.height) / tex.height);
                    info.uvTopRight = new Vector2((float)(rect.x + rect.width) / tex.width, (float)(rect.y + rect.height) / tex.height);
                    //设置字符顶点的偏移位置和宽高  
                    info.minX = 0;
                    info.minY = -(int)rect.height - offsetY;
                    info.maxX = (int)rect.width;
                    info.maxY = -offsetY;
                    //设置字符的宽度  
                    info.advance = (int)rect.width;
                    characterInfo[i] = info;
                }
                if (realIndex <= 0)
                {
                    Debug.Log("no valid sprite");
                    return;
                }
                Debug.Log("font sprites size = " + realIndex);
                var temp = new CharacterInfo[realIndex];
                for (int i = 0, temp_index= 0; temp_index < realIndex && i < characterInfo.Length; ++i)
                {
                    if (flags[i])
                    {
                        temp[temp_index++] = characterInfo[i];
                    }
                }
                // lineSpace += 2;  
                m_myFont.characterInfo = temp;
                EditorUtility.SetDirty(m_myFont);//设置变更过的资源  
                AssetDatabase.SaveAssets();//保存变更的资源  
                AssetDatabase.Refresh();//刷新资源,貌似在Mac上不起作用  

                //由于上面fresh之后在编辑器中依然没有刷新,所以暂时想到这个方法,  
                //先把生成的字体导出成一个包,然后再重新导入进来,这样就可以直接刷新了  
                //这是在Mac上遇到的,不知道Windows下面会不会出现,如果不出现可以把下面这一步注释掉  
                AssetDatabase.ExportPackage(fontPathName, "temp.unitypackage");
                AssetDatabase.DeleteAsset(fontPathName);
                AssetDatabase.ImportPackage("temp.unitypackage", true);
                AssetDatabase.Refresh();

                //最佳高度:上下各留一个像素的间距,如果不需要可以注释掉,根据需求更改  
                //打印是为了使使用者方便填写行高,因为font不支持设置行高。  
                Debug.Log("创建字体成功, 最大高度:" + lineSpace + ", 最佳高度:" + (lineSpace + 2));
            }
            else
            {
                Debug.LogWarning("没有选中Sprite文件,需要将Sprite放到Resources文件夹下面,可以参考函数上方的说明操作");
            }
        }
    }
}
  1. 选中BattleTextFont.png图片,点击CreateMyFontSprite,将会自动生成字体文件BattleTextFont.matBattleTextFont.fontsettings
    在这里插入图片描述
  2. 测试:新建UI -> Text,字体选为BattleTextFont
    在这里插入图片描述
  3. 最终效果
    在这里插入图片描述

字符间距调整技巧

  • 可以修改fontsettingsCharacter Rects里面元素中的Vert->WAdvance均能达到效果
  • 还可以修改fontsettings里的Tracking
    在这里插入图片描述

其他

  1. 修改UI text的四种方式
  2. Unity/UI —— 使用字符图片自定义字体(Custom Font)
  3. Custom Font不足
    • 无法定义中文字体。这点是由于Custom Font使用Ascii字符集导致的,Ascii字符集并不包含汉字。
    • 无法通过Size改变字体大小。 就像上一节的演示图一样,数字“1”显然比Text文本框的范围还要高,这是因为Custom Font本身无法改变字符大小,不过依然可以通过Scale来变相调节
    • 无法得到理想的字体颜色。 当改变Color,会在原图片的基础上变化,所以为了得到最好的显示效果,最好保证 字体颜色是白色,背景为透明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值