使用BMFont创建适用于Unity的艺术字

ops/2024/12/15 19:28:44/

最近经常使用艺术字,虽然之前的工作经验我知道只需要修什么哪些就可以弄好艺术字的创建和间隔,所以打算做个总结,接下来分为以下几步(其中会有补充,最后会有如何解决unity艺术字的字距问题)

第1步 下载BMFont

去官网下载即可BMFont官网,解压,64位就运行64位的exe程序

第2步 生成fnt文件

这里以0-9的数字图片为例子,图片如下:

打开之后,打开Options->Exprot Options,修改字体输出设置

至于内边距和间距一般不用管,然后打开Edit->Open Image Manager,点击Image,三个选项从上到下分别是导入图片、编辑图片(需要点击选中某行)、删除图片(同前一样需要选中)

这里点击导入图片,选中你的图片,假设你选的字符是0,那么选择好图片后,出现了这个页面,检查路径没问题,接下来是填入替换字符的id

如下图,鼠标放到替换字符处,前面的第一个就是id,该id为48,确定之后,开始选中这些需要导出的字符,亮色的就是选中的,左下角有你选中字符数

然后输出即可

补充:

BMFont官网文档

第三步 使用unity生成字体文件(.fontsettings)

添加脚本(非本人所写,这是我觉得写的不错的一个脚本)

,使用也很简单,只需要把.fnt和生成的图集一起导入unity,然后是三个参数的导入,fnt文件拖入第一个框内,第二个可以直接省略,第三个也可以省略,然后直接点击生成,字体就会出现在和fnt文件同目录下

文章链接:https://blog.csdn.net/w0100746363/article/details/105637683

using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEngine;public class BMFont : EditorWindow
{private TextAsset _fontTextAsset;private Texture _fontTexture;private string _fontsDir;[MenuItem("FontTools/BMFont", false, 12)]private static void BMFontTools(){BMFont bmFont = new BMFont();bmFont.Show();}private string _getAssetPath(string path){string pathTemp = path.Replace("\\", "/");pathTemp = pathTemp.Replace(Application.dataPath, "Assets");return pathTemp;}void OnGUI(){EditorGUILayout.BeginVertical();TextAsset taTemp = EditorGUILayout.ObjectField("选择Font文件:", _fontTextAsset, typeof(TextAsset), true) as TextAsset;if (taTemp != _fontTextAsset && taTemp != null){string assetDir = Directory.GetParent(AssetDatabase.GetAssetPath(taTemp)).FullName;assetDir = _getAssetPath(assetDir);string imgPath = string.Format("{0}/{1}_0.png", assetDir, taTemp.name);_fontTexture = AssetDatabase.LoadAssetAtPath<Texture>(imgPath);_fontsDir = string.Format("{0}.fontsettings", Path.Combine(assetDir, taTemp.name));if (_fontTexture == null){_fontsDir = string.Empty;Debug.LogError(string.Format("未发现{0}文件", imgPath));}}_fontTextAsset = taTemp;_fontTexture = EditorGUILayout.ObjectField("选择Font图片文件:", _fontTexture, typeof(Texture), true) as Texture;GUI.enabled = false;_fontsDir = EditorGUILayout.TextField("字体生成路径:", _fontsDir);GUI.enabled = true;if (GUILayout.Button("Generate Font")){if (!string.IsNullOrEmpty(_fontsDir)){Material mat = AssetDatabase.LoadAssetAtPath<Material>(_fontsDir.Replace(".fontsettings", ".mat"));if (mat == null){mat = new Material(Shader.Find("UI/Default Font"));AssetDatabase.CreateAsset(mat, _fontsDir.Replace(".fontsettings", ".mat"));}if (_fontTexture != null){mat = AssetDatabase.LoadAssetAtPath<Material>(_fontsDir.Replace(".fontsettings", ".mat"));mat.SetTexture("_MainTex", _fontTexture);}else{Debug.LogError("贴图未做配置,请检查配置");return;}Font font = AssetDatabase.LoadAssetAtPath<Font>(_fontsDir);if (font == null){font = new Font();AssetDatabase.CreateAsset(font, _fontsDir);}_setFontInfo(AssetDatabase.LoadAssetAtPath<Font>(_fontsDir),AssetDatabase.GetAssetPath(_fontTextAsset),_fontTexture);font = AssetDatabase.LoadAssetAtPath<Font>(_fontsDir);font.material = mat;}else{Debug.LogError("创建失败,请检查配置");}}EditorGUILayout.EndVertical();}private void _setFontInfo(Font font, string fontConfig, Texture texture){XmlDocument xml = new XmlDocument();xml.Load(fontConfig);List<CharacterInfo> chtInfoList = new List<CharacterInfo>();XmlNode node = xml.SelectSingleNode("font/chars");foreach (XmlNode nd in node.ChildNodes){XmlElement xe = (XmlElement)nd;int x = int.Parse(xe.GetAttribute("x"));int y = int.Parse(xe.GetAttribute("y"));int width = int.Parse(xe.GetAttribute("width"));int height = int.Parse(xe.GetAttribute("height"));int advance = int.Parse(xe.GetAttribute("xadvance"));CharacterInfo info = new CharacterInfo();info.glyphHeight = texture.height;info.glyphWidth = texture.width;info.index = int.Parse(xe.GetAttribute("id"));//这里注意下UV坐标系和从BMFont里得到的信息的坐标系是不一样的哦,前者左下角为(0,0),//右上角为(1,1)。而后者则是左上角上角为(0,0),右下角为(图宽,图高)info.uvTopLeft = new Vector2((float)x / texture.width, 1 - (float)y / texture.height);info.uvTopRight = new Vector2((float)(x + width) / texture.width, 1 - (float)y / texture.height);info.uvBottomLeft = new Vector2((float)x / texture.width, 1 - (float)(y + height) / texture.height);info.uvBottomRight = new Vector2((float)(x + width) / texture.width, 1 - (float)(y + height) / texture.height);info.minX = 0;info.minY = -height;info.maxX = width;info.maxY = 0;info.advance = advance;chtInfoList.Add(info);}font.characterInfo = chtInfoList.ToArray();AssetDatabase.Refresh();}
}

其中代码最关键的部分就是BMFontuv坐标转换到unity下的uv坐标,这里代码的意思也很简单就是循环取出图集中的每张图(制作fnt字体时不是有张图吗,那个就是图集),然后每张图转换uv坐标即可。

BMFontuv坐标,左上角(0,0),右下角为(宽度,高度)

Unity的uv坐标,左下角(0,0),右上角(1,1)

计算就如下图(自己打的手稿哈哈)

UV坐标是建立在一张图(纹理)上的。UV坐标是一个二维坐标系统,用于指定纹理图像上的具体位置,以便将纹理映射到三维模型的表面或二维图形上。这里的“一张图”指的是纹理图像,它包含了将要被映射的像素数据。

uv坐标参考博客:

Unity里的UV到底是什么 - cancantrbl - 博客园

Unity中Mesh的uv坐标讨论与使用方法_unity mesh uv-CSDN博客

解决unity艺术字的字距

通过 Tracking 设置可修改每个字符与同一行下一个字符的接近程度,而通过 Line spacing 设置可定义每行与下一行的接近程度

了解Font文件:Unity官网文档

注意

修改Tracking后需要运行(重新编译后才会生效)


http://www.ppmy.cn/ops/142185.html

相关文章

【人工智能-中级】卷积神经网络(CNN)的中阶应用:从图像分类到目标检测

文章目录 卷积神经网络(CNN)的中阶应用:从图像分类到目标检测1. 图像分类:CNN的基础应用CNN结构概述经典网络架构2. 目标检测:从分类到定位基于区域的目标检测方法单阶段目标检测方法边界框回归与NMS(Non-Maximum Suppression)3. 深度学习中的目标检测挑战与解决方案4. …

数组专题leetcode

链表适合插入、删除&#xff0c;时间复杂度 O(1) 数组是适合查找操作&#xff0c;但是查找的时间复杂度并不为 O(1)。即便是排好序的数组&#xff0c;你用二分查找&#xff0c;时间复杂度也是 O(logn) 数组&#xff1a;内存连续的存储相同类型 【数组插入】: 如果在数组的末…

Android中bindService和startService启动服务有何区别

Android中bindService和startService启动服务有何区别 bindService 和 startService 是 Android 中两种用于与 Service 交互的方式&#xff0c;它们的区别主要在于 生命周期管理 和 使用场景。以下是详细对比&#xff1a; 1. bindService方式 bindService 是一种绑定方式&am…

【大语言模型】ACL2024论文-25 微妙偏见需要更微妙的衡量:双重指标评估大型语言模型中的代表性和亲和力偏见

【大语言模型】ACL2024论文-25 微妙偏见需要更微妙的衡量&#xff1a;双重指标评估大型语言模型中的代表性和亲和力偏见 目录 文章目录 【大语言模型】ACL2024论文-25 微妙偏见需要更微妙的衡量&#xff1a;双重指标评估大型语言模型中的代表性和亲和力偏见目录文章信息摘要研究…

专业140+总分400+北京理工大学826信号处理导论考研经验北理工电子信息与通信工程,真题,大纲,参考书。

考研总分400&#xff0c;专业826信号处理导论&#xff08;信号与系统和dsp&#xff09;140&#xff0c;成功上岸北理工&#xff0c;虽然已经一段时间&#xff0c;但是后劲很大&#xff0c;每每回想还是昨日事&#xff0c;群里同学多次要求分享自己的一些经验&#xff0c;感谢大…

etcd命令大全

默认安装自带etcdctl 命令行客户端&#xff0c;分两个版本ETCDCTL_API2和ETCDCTL_API3&#xff0c;两个版本不一样&#xff0c;操作的数据也不相容。 本文以v3 为例。 使用之前需要先设置&#xff1a;export ETCDCTL_API3。 1 etcd查询集群节点列表及状态 标准输出&#xff1…

12月第一讲堂:CDP与Selenium相结合

Selenium Selenium 是一款开源且可移植的自动化软件测试工具&#xff0c;专门用于测试网页端应用程序或者采集网页端数据。它能够在不同的浏览器和操作系统上运行&#xff0c;具有很强的跨平台能力。Selenium可以帮助测试人员更高效地自动化测试基于Web网页端的应用程序&#…

vue3+vite+ts 使用webrtc-streamer播放海康rtsp监控视频

了解webrtc-streamer webrtc-streamer 是一个使用简单机制通过 WebRTC 流式传输视频捕获设备和 RTSP 源的项目&#xff0c;它内置了一个小型的 HTTP server 来对 WebRTC需要的相关接口提供支持。相对于ffmpegflv.js的方案&#xff0c;延迟降低到了0.4秒左右&#xff0c;画面的…