本文参考了这片博客文章,在此基础上进行优化和改进:

https://blog.csdn.net/akof1314/article/details/80868869

先截张效果图:

TextMeshPro在之前的博客中有介绍:

https://www.cnblogs.com/koshio0219/p/11643268.html

思来想去,这东西还是有些使用不方便的地方,问题的根本还是在于中文字库太多,虽然缩减为7000简体字库或3500简体字库可以解决问题。

但无论怎么说,游戏中大量的字其实是没有用到的,这势必会造成资源浪费。

于是,接下来的想法也就应运而生——为什不能找到游戏中所有用到的字,只将这些字渲染进纹理图呢,有新增的字就更新下字库和纹理图就好了。

这也就是上面这个工具诞生的最主要原因,它主要为了实现:

1.批量查找游戏中Canvas或其他GameObject上的文字内容

2.扫描查找指定路径下的配置文件中文本内容

3.将这些文本去除重复字符后保存到一个固定的输出路径

4.根据输出的游戏文本内容按照想要生成的TMP字体类型批量一键生产和更新

5.随时批量修改Canvas上的字体资源

下面是一些相对具体的思路:

查找Canvas中的文字资源很简单,只需要遍历所有的对应组件上的内容就行了:

 string newText = "";
foreach (var targetCanvas in targetCanvasList)
{
TextMeshProUGUI[] textMeshProUGUIs = targetCanvas.GetComponentsInChildren<TextMeshProUGUI>(true);
foreach (var item in textMeshProUGUIs)
{
newText += item.text;
}
}

对于配置文件,需要在指定的文件夹路径中查找:

 private void FindTextAssets(string textAssetPath)
{
textAssetList.Clear();
if (Directory.Exists(textAssetPath))
{
DirectoryInfo info = new DirectoryInfo(textAssetPath);
FileInfo[] files = info.GetFiles("*", SearchOption.AllDirectories); for (int i = ; i < files.Length; i++)
{
//去除meat文件
if (!files[i].Name.EndsWith(".csv.meat"))
{
var str = File.ReadAllText(files[i].ToString());
Debug.Log(str);
textAssetList.Add(str);
}
}
}
}

对于得到的文字,每次更新时进行字符去重,去空格,去换行:

 private string StrCutRepeat(string oriStr)
{
return string.Join("", oriStr.ToArray().Distinct().ToArray()).Replace("\n", "").Replace(" ", "");
}

上面的需要用到以下命名空间:

using System.IO;
using System.Linq;

每次更新完文本内容需要刷新资源:

AssetDatabase.Refresh();

清理文本资源:

 private void ClearTextAsset(string path)
{
if (File.Exists(path))
{
File.WriteAllText(path, "X");
AssetDatabase.Refresh();
}
}

单个TMP字体纹理的生成功能在插件中已经有了,这里只需要实现选择控制和按顺序批量生产就可以了。

在Updata()中检测上一个字体资源的生成进度,按百分比显示,当生成完成时循环生成下一个即可:

 private void MyUpdate()
{
if (m_IsRepaintNeeded)
{
m_IsRepaintNeeded = false;
Repaint();
} // 第一步创建字体渲染数组
if (m_IsProcessing)
{
m_AtlasGenerationProgress = FontEngine.generationProgress;
m_FontAssetInfos[m_CurGenerateIndex].genPercent = m_AtlasGenerationProgress * ; m_IsRepaintNeeded = true;
} // 是否生成完
if (m_IsRenderingDone)
{
m_IsProcessing = false;
m_IsRenderingDone = false; if (m_IsGenerationCancelled == false)
{
// 第二步输出渲染结果
UpdateRenderFeedbackWindow();
// 第三步将渲染数组填充到纹理贴图(注意,贴图共享不删除)
CreateFontTexture();
foreach (var asset in m_FontAssetInfos[m_CurGenerateIndex].assets)
{
//保存信息到字体资产
Save_SDF_FontAsset(asset);
}
// 最后置空
m_FontAtlasTexture = null;
}
Repaint();
//开始循环生成下一个资源
GenerateNext();
}
else if (m_LoadFontFaceInMainThread == )
{
FontEngineError errorCode = FontEngine.LoadFontFace(m_LoadFontFaceInMainThreadFontPath);
m_LoadFontFaceInMainThread = errorCode == FontEngineError.Success ? : ;
}
}
 private void GenerateNext()
{
m_CurGenerateIndex++;
//判断是否所有资源序列已经执行完
if (m_CurGenerateIndex >= m_FontAssetInfos.Count)
{
EditorUtility.DisplayDialog("提示", "生成字库资产成功!", "OK");
return;
} //判断资源信息的生成开关是否已经开启
var info = m_FontAssetInfos[m_CurGenerateIndex];
if (!info.toggle)
{
GenerateNext();
return;
} //得到资源路径下的文件
m_SourceFontFile = AssetDatabase.LoadAssetAtPath<Font>(info.fontPath);
//具体生成流程
GenerateFontAtlasButton();
}

批量赋值字体资源:

 private void AttachFontAsset()
{
foreach (var targetCanvas in attachCanvasList)
{
TextMeshProUGUI[] textMeshProUGUIs = targetCanvas.GetComponentsInChildren<TextMeshProUGUI>(true);
foreach (var item in textMeshProUGUIs)
{
item.font = tmpFontAsset;
}
}
}

Editor窗口显示部分:

大部分的Editor显示功能都是非常基础的,这里记录下几个不太常用的功能的实现:

1.显示需要序列化的属性,例如要序列化List:

先定义两个属性,一个是需要序列化的属性,另一个是该序列化属性对应的对象,如下:

[SerializeField]
List<GameObject> targetCanvasList = new List<GameObject>(); SerializedProperty _canvasPropertyt;

在OnEnable()中进行序列化对象的初始化和对应属性查找赋值:

 public void OnEnable()
{
_serializedObject = new SerializedObject(this);
_canvasPropertyt = _serializedObject.FindProperty("targetCanvasList");
}

在绘制函数中对序列化对象进行修改更新的检测,并随时提交修改,例如:

 public void OnGUI()
{
_serializedObject.Update(); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_canvasPropertyt, true); if (EditorGUI.EndChangeCheck())
_serializedObject.ApplyModifiedProperties();
}

注意在函数EditorGUILayout.PropertyField中第二个参数一定要赋值为true,不然序列化属性的子对象无法显示。

2.点击控制标题——折叠式开关的开启与关闭:

 public void OnGUI()
{
bShowFontWorld = EditorGUILayout.Foldout(bShowFontWorld, "Font Word", true, EditorStyles.foldoutPreDrop); if (bShowFontWorld)
{
//折叠开关开启时需要显示的内容
}
}

函数EditorGUILayout.Foldout会自动在显示内容左侧创建小三角Icon,四个参数意义分别是:

1.控制点击时是否显示折叠的内容,为true时显示折叠内容

2.具体的显示内容标题

3.控制开关的检测区域是否包含标题内容区域本身,还是只包含开关Icon部分,为true时全部包含

4.风格设置,这里的风格最好选择带有foldout类型的,不然无法自动创建小三角Icon

函数返回当前用户的操作——是否开启折叠内容。

3.Object拾取器:

tmpFontAsset = (TMP_FontAsset)EditorGUILayout.ObjectField("Font Asset", tmpFontAsset, typeof(TMP_FontAsset),false);

最后一个参数为是否允许拾取场景中的物体,返回的是一个Object对象,需要进行强制类型转换。

Unity TextMeshPro 一键生成工具的更多相关文章

  1. PICT工具一键生成正交试验用例

    PICT工具一键生成正交试验用例 作用: 1.解决手动设计大量测试用例.或覆盖不全面问题,提高测试效率 2.读取excel,将生成的参数组合自动带入脚本,进行接口自动化测试 一.PICT简介 PICT ...

  2. [Java 开源项目]一款无需写任何代码,即可一键生成前后端代码的工具

    作者:HelloGitHub-小鱼干 JeecgBoot 是一款基于代码生成器的低代码开发平台,零代码开发.JeecgBoot 采用开发模式:Online Coding 模式-> 代码生成器模式 ...

  3. Unity自己主动打包工具

    最開始有写打包工具的想法,是由于看到<啪啪三国>王伟峰分享的一张图,他们有一个专门的"工具程序猿"开发各种工具. (ps:说起来这个王伟峰和他的创始团队成员,曾经跟我是 ...

  4. 【C#附源码】数据库文档生成工具支持(Excel+Html)

    [2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...

  5. 数据库文档生成工具——word2chm,SqlSpec

    首先使用代码生成器可以生成word版本的数据库文档. 转成chm格式的更加小巧和方便~ SqlSpec是个好工具,可以生成所有数据库相关的信息 之后可以一键生成chm文档.

  6. Asp.net mvc 5 CRUD代码自动生成工具- vs.net 2013 Saffolding功能扩展

    Asp.net mvc 5 CRUD代码自动生成工具 -Visual Studio.net2013 Saffolding功能扩展 上次做过一个<Asp.net webform scaffoldi ...

  7. 根据已有的Jar包 一键生成对应的mavenpom.xml信息

    根据已有的jar包信息一键生成对应的maven坐标信息 .想一个问题 假如 我有一个SSH的项目, jar包是配置在lib中, 我现在想把它做成maven格式的SSH项目  ,那么这些jar包在mav ...

  8. Unity中一键创建常用文件夹

    Unity中一键创建常用文件夹 说明 项目测试版本Unity5.3. 这个一个小工具:功能非常简单,就是一键给新建工程添加所有文件夹.到此结束. 但是具体咋操作呢? 与把大象装进冰箱一样,三步,下载代 ...

  9. 一键生成属于自己的QQ历史报告,看看你对自己的QQ了解程度有多深?

    目录 一键生成属于自己的QQ历史报告,看看你对自己的QQ了解程度有多深? 简介 功能截图 如何运行 编写思路 main.py模块 qq_bot模块 tkinter_gui模块 static_data模 ...

随机推荐

  1. [Go] 利用函数类型实现封装中的回调

    当进行业务逻辑开发的时候,经常要进行封装,封装成独立的类文件,在类文件的属性中预留出函数类型的API 在调用该类文件中某些方法的时候,也根据业务需要调用类属性中的函数, 在主业务中可以传递特定的函数注 ...

  2. Linux系统学习 十二、VSFTP服务—简介与原理

    1.简介与原理 互联网诞生之初就存在三大服务:WWW.FTP.邮件 FTP主要针对企业级,可以设置权限,对不同等级的资料针对不同权限人员显示. 但是像网盘这样的基本没有权限划分. 简介: FTP(Fi ...

  3. 关于soapui接口的笔记

    1.接口包含内容 #request: HTTP版本/请求地址url 请求方法:GET.POST.PUT.DELETE等 请求头:content—type 请求正文:请求参数 #response: 状态 ...

  4. 给OPi Zero Plus添加USB启动功能

    为使OPi Zero Plus支持U盘启动,需要在板载的SPI Flash当中刷入uboot.在这个过程当中绕了很多弯路,特此记录 最终操作步骤见文末 网上的教程仅使用sudo modprobe sp ...

  5. Appium+Java 自动化测试系列二:Maven+Testng

    新建Maven项目作为测试项目分为3个步骤: 1.Eclipse安装Testng 插件 2.新建Maven项目 3.引入Testng 一.Eclipse安装Testng插件 TestNG安装可选择在线 ...

  6. Cypress 之 环境配置

    将项目添加到cypress时,cypress.json会在项目中创建一个文件,此文件用于存储projectId,以及你提供的任何配置项. { "projectId": " ...

  7. 即将是史上最全的meta大全

    本文的目的是搜集当前主流的meta配置,方便开发者快速开发调试.在这里不会做各种meta的深入分析,只是简单的介绍,让大家知道有这个东西. meta简述 meta用于描述 HTML 文档的元数据.通常 ...

  8. 基于SSM的crm管理系统

    学完crm后的第一个项目实践,前端样式与标签库都是现成的. 开发环境 eclipse,mysql,jdk1.7 项目架构 整合思路 Dao层: 1.SqlMapConfig.xml,添加别名,但是需要 ...

  9. ASP.NET Core 2.2 WebApi 系列【二】使用EF CodeFirst创建数据库

    Code First模式 Code First是指"代码优先"或"代码先行". Code First模式将会基于编写的类和配置,自动创建模型和数据库. 一.准备 ...

  10. Html5 Canvas动画基础碰撞检测的实现

    在Canvas中进行碰撞检测,大家往往直接采用游戏引擎(Cocos2d-JS.Egret)或物理引擎(Box2D)内置的碰撞检测功能,好奇的你有思考过它们的内部运行机制吗?下面将针对基本的碰撞检测技术 ...