欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity3D-将美术提供的图片当做字体使用(普通图片自动生成Custom font)

程序员文章站 2022-07-02 14:29:49
...

参考:http://blog.csdn.net/pz789as/article/details/54313122

我在上一篇文章中写了一个最新版本的导出fnt字体的方式,主要就是uv和vert的变化。
这两天发现,有时候我们需要的艺术字体,并不是ttf这种字体格式的文件,而有可能是美术人员自己动手画的艺术字,这个时候就没法用上面那个方法去做图片字体了。难道还能用手去填写么,那也太麻烦了。
本来想着自己写个工具去切分然后导出,后面想到为什么不利用unity自带的sprite editor呢?
于是在网上搜索,发现是可以写一个编辑器脚本去读取sprite的,而且是那种切分的sprite。
具体做法如下,版本是Unity5.5:
1、把字体图片导入到unity中来,需要将文件放到Resources文件夹下面。看到这里我想大家都明白怎么弄了,对的,就是使用Resources.Load()的方法去加载;
2、设置图片的格式为sprite,sprite mode为multiple,alpha source根据图片去设置,带了alpha的就选择 input texture alpha,没有的就选择from gray scale,主要是设置透明;
Unity3D-将美术提供的图片当做字体使用(普通图片自动生成Custom font)

3、使用unity自带的sprite edtior,将我们的艺术字体图片一个一个的切分好,然后命名自己规范一下!我现在命名是使用的名字的最后一个字符去定义的,类似我下面的截图:
Unity3D-将美术提供的图片当做字体使用(普通图片自动生成Custom font)
这样做的好处是我们在代码里面得到这个字符的ascii码,直接对应了字体里面的index,而且看起来也直观了当。当然如果是汉字的话,那么就得自己去做一个映射了,使用一些不常用的字符去替换即可。
4、然后我们在看看这个还可以给我们提供什么数据呢?那就是pivot了,一般来说我们做到这个一步就可以了,但是有一个额外的pivot为什么不利用起来呢!我现在是把这个当做一个偏移去用的,因为有些符号:比如“,”、“.”这种,是需要居底显示的。因此我就用这个来代替,但是具体要怎么计算,就看大家各自的用处了。
5、准备资源完毕后,接下来就是写代码了,我就不多说了,直接贴上来吧:

//本方法是通过裁切的sprite导出字体文件,裁切使用的是unity自带的sprite editor,方便操作。  
    //另外,裁切之后,每个sprite的名字的最后一个字符对应了ascii码的编码,比如:  
    //0: 我们只要将sprite的名字命名成xxx0,就可以了!  
    //由于使用到的了sprite加载,所以字体图片请放在Resources目录下面,等制作完毕,再把他们放到fonts文件夹或者其他文件夹中即可。  
    [MenuItem("Assets/CreateMyFontSprite")]  
    static void CreateMyFontSprite(){  
        if (Selection.objects == null) return;  
        if (Selection.objects.Length == 0) {  
            Debug.LogWarning("没有选中Sprite文件,需要将Sprite Mode设置成Multiple,切分好,并且以以名字的最后一个字符当做ascii码");  
            return;  
        }  
        string resoursePath = "Resources";  
        Object o = Selection.objects[0];  
        if (o.GetType() != typeof(Texture2D)){  
            Debug.LogWarning("选中的并不是图片文件");  
            return;  
        }  
        string selectionPath = AssetDatabase.GetAssetPath(o);  
        if (selectionPath.Contains(resoursePath)){  
            string selectionExt = Path.GetExtension(selectionPath);  
            if (selectionExt.Length == 0){  
                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);  
            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];   
                //得到最高的高度,设置行高和进行偏移计算  
                for(int i=0;i<sprites.Length;i++){  
                    if (sprites[i].rect.height > lineSpace){  
                        lineSpace = sprites[i].rect.height;  
                    }  
                }  
                for(int i=0;i<sprites.Length;i++){  
                    Sprite spr = sprites[i];  
                    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;  
                }  
                // lineSpace += 2;  
                m_myFont.characterInfo = characterInfo;  
                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文件夹下面,可以参考函数上方的说明操作");  
            }  
        }  
    }  

这个方法的好处就是不需要使用BMFont软件去导出字体数据了,而且可以做各种自己需要的字体或者图片效果。我这里也沿用了前一篇文章的做饭,只需要选择这个图片文件,然后点菜单栏中的按钮就可以生成想要的字体咯!

注意的地方:
1、图片的设置格式;
2、图片放置的位置;
3、切分图片的名字;
4、最最重要的是,当你把字体做完之后,需要将图片格式重新设置成Default,不然上了真机会出现你想不到的效果~
微笑