unity使用BMFont制作位图字体

简介: unity也能制作艺术字拉

介绍

在游戏中制作中,我们往往会遇到自定义字体的情况,但是unity自带的字体Arial,无法满足我们对字体的需求。虽然我们可以导入字体,但是并不一定符合我们的需要,这个时候就需要使用自定义字体来显示某些东西以达到某种视觉效果,例如:
在这里插入图片描述

BmFont准备

http://www.angelcode.com/products/bmfont/

认识bmFont

首先,双击安装好的软件
在这里插入图片描述
软件打开,初始界面如下:
在这里插入图片描述
是不是看上去密密麻麻,手足无措,不要担心,很简单的,我们一步一步来。

上方选择区域

在这里插入图片描述

可以看到的是上方选择区域只有两个,Options和Edit。

  • Options主要是对整张位图字体的操作
  • Edit是对里面单个或多个字符的操作。

用个形象的比喻:一张纸代表Options,纸张的大小等设置是Options管理;而里面的每一个字符,则有Edit决定。这样比喻形象多了吧~

中间区域

中间区域几乎包含了所有常见的字符
在这里插入图片描述
右边区域可以暂时不用管,目前也没用到过,目测应该是语言字体之类的。

右下方

就制作位图字体而言,右下方提供给我们一个字符对应的id(即ASCII码)
在这里插入图片描述

制作位图字体

首先,我们来制作一个字符:
Edit–>OpenImgageManager,打开ImageManager界面
在这里插入图片描述

Image->importImage,选择图片
在这里插入图片描述
选择要导入的一张字符图片后会出现如下弹窗:
在这里插入图片描述
注意Id,id对应字符的ASCII码。

那么,如何知道某个字符的id或者ASCII码呢,接下来就回到上文了,还记得上文介绍BmFont界面时的介绍的右下方吗,第一个值(48)就是我们需要填写的id值。

那么这时候问题又来了,如何查看每个字符的id值呢?不要担心,其实很简单,只需要把鼠标移动到中间区域对应的字符上,即可在右下方查看,如图所示:
在这里插入图片描述

导入成功后,我们会在ImageManager界面看到字符信息:
左边代表id,右边是对应的美术资源路径。
在这里插入图片描述
回到BM Font主界面,可以看,对应字符右下角有一个小标志,该标志代表制作成功的字符。
在这里插入图片描述
当我们把需要制作的位图字体导入成功后,接下来就是设置位图了。选择Options->Export options
在这里插入图片描述
打开导出选项界面。

  1. 设置整张位图的长款。
  2. 设置字体的导出格式。
  3. 确认设置。

在这里插入图片描述
接下来就是保存位图了,选择Options-> Save bitmap font as
在这里插入图片描述
选择你要保存的路径,并修改命名,这里我改为test并保存。保存成功后会得到两个文件,分别是.png和.fnt
在这里插入图片描述
至此,位图字体就已经制作完成了,接下来了解在Unity中使用该字体吧!

Unity使用位图字体

新建Font文件夹,并将上面制作好的位图字体拖·进去。
在这里插入图片描述
新建一个Materia设置如下:shader–>TextShader
在这里插入图片描述
并设置FontTexture的值如下(即上文提到的.png文件):在这里插入图片描述

新建CustomFont,将上文创建的材质球拖到如图所示位置,设置如下:
在这里插入图片描述
下面,用个动图介绍一下位图字体在unity中的使用准备:
在这里插入图片描述
正当你以为结束的时候,你会发现新建Text,使用新字体,没有任何显示,这时候你查看会发现test.mat里面是空的。
在这里插入图片描述
这时候不要急,下面我们就来为test.mat复制,新建C#脚本CustomFontImportor,添加如下代码:

using UnityEngine;
using System.Collections;
using System.Xml;
using System;


public class CustomFontImportor : MonoBehaviour
{
    public Font font;
    public TextAsset textAsset;


    void Awake()
    {
        if (font == null || textAsset == null)
        {
            //Debug.LogError("请设置font和textAsset.");
            return;
        }

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(textAsset.text);


        int totalWidth = Convert.ToInt32(xmlDocument["font"]["common"].Attributes["scaleW"].InnerText);
        int totalHeight = Convert.ToInt32(xmlDocument["font"]["common"].Attributes["scaleH"].InnerText);

        XmlElement xml = xmlDocument["font"]["chars"];
        ArrayList characterInfoList = new ArrayList();


        for (int i = 0; i < xml.ChildNodes.Count; ++i)
        {
            XmlNode node = xml.ChildNodes[i];
            if (node.Attributes == null)
            {
                continue;
            }
            int index = Convert.ToInt32(node.Attributes["id"].InnerText);
            int x = Convert.ToInt32(node.Attributes["x"].InnerText);
            int y = Convert.ToInt32(node.Attributes["y"].InnerText);
            int width = Convert.ToInt32(node.Attributes["width"].InnerText);
            int height = Convert.ToInt32(node.Attributes["height"].InnerText);
            int xOffset = Convert.ToInt32(node.Attributes["xoffset"].InnerText);
            int yOffset = Convert.ToInt32(node.Attributes["yoffset"].InnerText);
            int xAdvance = Convert.ToInt32(node.Attributes["xadvance"].InnerText);
            CharacterInfo info = new CharacterInfo();
            Rect uv = new Rect();
            uv.x = (float)x / totalWidth;
            uv.y = (float)(totalHeight - y - height) / totalHeight;
            uv.width = (float)width / totalWidth;
            uv.height = (float)height / totalHeight;
            info.index = index;
            info.uvBottomLeft = new Vector2(uv.xMin, uv.yMin);
            info.uvBottomRight = new Vector2(uv.xMax, uv.yMin);
            info.uvTopLeft = new Vector2(uv.xMin, uv.yMax);
            info.uvTopRight = new Vector2(uv.xMax, uv.yMax);
            info.minX = xOffset;
            info.maxX = xOffset + width;
            info.minY = -yOffset - height;
            info.maxY = -yOffset;
            info.advance = xAdvance;
            info.glyphWidth = width;
            info.glyphHeight = height;
            characterInfoList.Add(info);
        }
        font.characterInfo = characterInfoList.ToArray(typeof(CharacterInfo)) as CharacterInfo[];
        Debug.Log("生成成功.");
    }
}

将CustomFontImportor脚本拖到场景中的物体身上,并运行场景,我们会可看到有一个“生成成功”的日志输出,这是选中test.mat查看发现,已经被成功赋值了。
在这里插入图片描述
接下来你就可以Unity中肆无忌惮的使用新制作的位图字体拉~

相关文章
|
图形学 Android开发
Unity从学习到赚钱系列-聊天气泡及字体模糊
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
340 0
|
vr&ar 图形学
【Unity3D 灵巧小知识点】☀️ | Unity控制台 输出打印不同颜色的字体
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 也可以简单把 Unity 理解为一个游戏引擎,可以用来专业制作游戏!
【Unity3D 灵巧小知识点】☀️ | Unity控制台 输出打印不同颜色的字体
|
3月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
176 6
|
2月前
|
测试技术 C# 图形学
掌握Unity调试与测试的终极指南:从内置调试工具到自动化测试框架,全方位保障游戏品质不踩坑,打造流畅游戏体验的必备技能大揭秘!
【9月更文挑战第1天】在开发游戏时,Unity 引擎让创意变为现实。但软件开发中难免遇到 Bug,若不解决,将严重影响用户体验。调试与测试成为确保游戏质量的最后一道防线。本文介绍如何利用 Unity 的调试工具高效排查问题,并通过 Profiler 分析性能瓶颈。此外,Unity Test Framework 支持自动化测试,提高开发效率。结合单元测试与集成测试,确保游戏逻辑正确无误。对于在线游戏,还需进行压力测试以验证服务器稳定性。总之,调试与测试贯穿游戏开发全流程,确保最终作品既好玩又稳定。
105 4
|
3月前
|
图形学 缓存 算法
掌握这五大绝招,让您的Unity游戏瞬间加载完毕,从此告别漫长等待,大幅提升玩家首次体验的满意度与留存率!
【8月更文挑战第31天】游戏的加载时间是影响玩家初次体验的关键因素,特别是在移动设备上。本文介绍了几种常见的Unity游戏加载优化方法,包括资源的预加载与异步加载、使用AssetBundles管理动态资源、纹理和模型优化、合理利用缓存系统以及脚本优化。通过具体示例代码展示了如何实现异步加载场景,并提出了针对不同资源的优化策略。综合运用这些技术可以显著缩短加载时间,提升玩家满意度。
152 5
|
2月前
|
前端开发 图形学 开发者
【独家揭秘】那些让你的游戏瞬间鲜活起来的Unity UI动画技巧:从零开始打造动态按钮,提升玩家交互体验的绝招大公开!
【9月更文挑战第1天】在游戏开发领域,Unity 是最受欢迎的游戏引擎之一,其强大的跨平台发布能力和丰富的功能集让开发者能够迅速打造出高质量的游戏。优秀的 UI 设计对于游戏至关重要,尤其是在手游市场,出色的 UI 能给玩家留下深刻的第一印象。Unity 的 UGUI 系统提供了一整套解决方案,包括 Canvas、Image 和 Button 等组件,支持添加各种动画效果。
136 3
|
2月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
185 3