zoukankan      html  css  js  c++  java
  • 关于Unity中的Bmpfont的使用

    系统字体,不占空间,效果一般。

    自己拖的.TTF文件形成的字体,占空间很大,有特殊效果。一个TTF字库差不多占用3M左右,之所以这么大,是因为里面包含了所有的字,就像一本字典一样,所以字符都在里面。

    但是我们开发游戏,并不需要用到所有的字,有的时候可能就只用到其中的几十个字,所以可以用一种解决方案,使得文字的效果好,同时占很小的空间。

    这种方案就是Bmpfont,前提是有限的字符和好的字体。

    用工具GlyphDesigner (Mac系统),把有限的字符添加字体效果后,绘制在一张png大图上,同时附加一个.fnt的配置文件,里面记录了文字在图片中的位置坐标信息,用于匹配,如Advance表示的是下一个字符开始的位置

    就是说有了这个fnt文件,系统才能找到这个字在图片中的哪个位置,从而复制出来显示。

    一、Bmpfont

    1.把fnt文件和png文件拖进Resources文件夹下面

    2.创建一个Canvas

    3.对Canvas进行初始化,记得把Game视图的分辨率调成和Canvas里面设置的一样的分辨率640X960

    4.创建一个Image的UI节点作为Canvas的子节点,名字叫bg,拖进背景图片到这个节点中。

    5.创建一个Text类型的UI节点叫text

    6.创建一个类似TTF类型的字库资源文件在Resources文件下create--->custom font,名字改成和fnt文件一样

    7.创建一个材质球create--->material,名字改成和fnt文件一样,Shader属性改成GUI/Text Shader(用默认颜色覆盖原来颜色)或者Moboile/Diffuse(原样),把png图片设置为Sprite后拖进材质球的贴图属性。

    8.把类似TTF类型的字库资源文件的Default Material属性拖进第7步的材质球,再手动计算和输入每一个字符的参数属性,size=1表示只有一个字符,其他的参数在fnt文件里面找。

    计算公式:

    char id=52 x=2 y=2 width=25 height=33 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=0 letter="4"
    UV
    X = x / 贴图宽(2/128 = 0.015625) ; Y = 1 - y / 贴图高(1- 2/128 = 0.984375)
    W = width / 贴图宽(25/128 = 0.1953125) ; H = -1 * height / 贴图高 (-33/128 = -0.2578125)
    Vert
    X = xoffset (0) ; Y = yoffset (-0.5 * height)
    W = width(25) ; H = height(33) advance = xadvance (20);

    9.把类似TTF类型的字库资源文件拖进text的UI节点的Character--->font字体属性中。

    10.text节点中的text属性里面输入想显示的字符,必须是在png图片中有的且被我们手动录入的字符。

    二、扩展编辑器

    上面第七步需要手动一个一个计算字符参数和添加字符进去,非常麻烦,有一种方案可以便捷一点,就是扩展编辑器

    1.在Assets文件夹下面创建一个叫做Editor的文件夹,必须叫这个,不然等下里面放的脚本会和平时写的脚本混在一起。

    2.把字符处理脚本(网上下载的),放进Editor文件夹下

    3.字符处理脚本CreateFontEditor:

    using UnityEngine;
    using UnityEditor;
    using System.Collections.Generic;
    using System.IO;
    using System.Text.RegularExpressions;
    
    // 创建bmfont  
    // 继承自编辑器的扩展,用来扩展我们的编辑器的,应该放到Editor这个目录下;
    
    public class CreateFontEditor : Editor
    {
        // 制定我们入口的菜单
        [MenuItem("Assets/Create/CreateBMFont")]
        static void CreateFont()
        {
            // 当前选择的物体
            Object obj = Selection.activeObject;
            // Unity API 返回当前你选择的资源的路径
            string fntPath = AssetDatabase.GetAssetPath(obj);
            Debug.Log("#####" + fntPath);
    
            // 程序需要从fnt文件里面导入我们字模信息;
            if (fntPath.IndexOf(".fnt") == -1)
            {
                // 不是字体文件  
                return;
            }
    
            // your_name.fnt --> your_name.fontsetting;名字一致
            // new path --> .fnt --> .fontsettings;
            string customFontPath = fntPath.Replace(".fnt", ".fontsettings");
            if (!File.Exists(customFontPath))
            {
                return;
            }
    
            Debug.Log(fntPath);
            StreamReader reader = new StreamReader(new FileStream(fntPath, FileMode.Open));
    
            List<CharacterInfo> charList = new List<CharacterInfo>();
    
            Regex reg = new Regex(@"char id=(?<id>d+)s+x=(?<x>d+)s+y=(?<y>d+)s+width=(?<width>d+)s+height=(?<height>d+)s+xoffset=(?<xoffset>d+)s+yoffset=(?<yoffset>d+)s+xadvance=(?<xadvance>d+)s+");
            string line = reader.ReadLine();
            int lineHeight = 0;
            int texWidth = 1;
            int texHeight = 1;
    
            while (line != null)
            {
                if (line.IndexOf("char id=") != -1)
                {
                    Match match = reg.Match(line);
                    if (match != Match.Empty)
                    {
                        var id = System.Convert.ToInt32(match.Groups["id"].Value);
                        var x = System.Convert.ToInt32(match.Groups["x"].Value);
                        var y = System.Convert.ToInt32(match.Groups["y"].Value);
                        var width = System.Convert.ToInt32(match.Groups["width"].Value);
                        var height = System.Convert.ToInt32(match.Groups["height"].Value);
                        var xoffset = System.Convert.ToInt32(match.Groups["xoffset"].Value);
                        var yoffset = System.Convert.ToInt32(match.Groups["yoffset"].Value);
                        var xadvance = System.Convert.ToInt32(match.Groups["xadvance"].Value);
    
                        CharacterInfo info = new CharacterInfo();
                        info.index = id;
                        float uvx = 1f * x / texWidth;
                        float uvy = 1 - (1f * y / texHeight);
                        float uvw = 1f * width / texWidth;
                        float uvh = -1f * height / texHeight;
    
                        info.uvBottomLeft = new Vector2(uvx, uvy);
                        info.uvBottomRight = new Vector2(uvx + uvw, uvy);
                        info.uvTopLeft = new Vector2(uvx, uvy + uvh);
                        info.uvTopRight = new Vector2(uvx + uvw, uvy + uvh);
    
                        info.minX = xoffset;
                        info.minY = yoffset + height / 2;   // 这样调出来的效果是ok的,原理未知  
                        info.glyphWidth = width;
                        info.glyphHeight = -height; // 同上,不知道为什么要用负的,可能跟unity纹理uv有关  
                        info.advance = xadvance;
    
                        charList.Add(info);
                    }
                }
                else if (line.IndexOf("scaleW=") != -1)
                {
                    Regex reg2 = new Regex(@"common lineHeight=(?<lineHeight>d+)s+.*scaleW=(?<scaleW>d+)s+scaleH=(?<scaleH>d+)");
                    Match match = reg2.Match(line);
                    if (match != Match.Empty)
                    {
                        lineHeight = System.Convert.ToInt32(match.Groups["lineHeight"].Value);
                        texWidth = System.Convert.ToInt32(match.Groups["scaleW"].Value);
                        texHeight = System.Convert.ToInt32(match.Groups["scaleH"].Value);
                    }
                }
                line = reader.ReadLine();
            }
    
            Font customFont = AssetDatabase.LoadAssetAtPath<Font>(customFontPath);
            customFont.characterInfo = charList.ToArray();
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            Debug.Log(customFont);
        }
    }

    4.添加好custom font资源文件的文字材质球后,对想要手动添加字符的custom font资源文件使用右键--->Create--->CreateBMFont就可以把fnt文件里面的每一个字符和它的参数都计算添加到custom font资源文件里面

    5.把custom font资源文件拖进text的UI节点的font属性,就可以使用了。

  • 相关阅读:
    c#之静态构造函数和单例模式
    ugui之圆角矩形头像实现
    一些网站
    unity3d之实现各种滑动效果
    unity3d之切换场景不销毁物体
    unity3d之技能栏冷却
    unity3d之控制人物转向移动并播放动画
    vs常用快捷键
    构造函数的继承
    编写可维护的javascript 随笔
  • 原文地址:https://www.cnblogs.com/HangZhe/p/6917408.html
Copyright © 2011-2022 走看看