目录

1.背景介绍

2.具体代码

3.Undo与Dirty

(1)Undo

(2)Dirty

4.文件路径的斜杠与反斜杠

5.该脚本的修改与拓展


1.背景介绍

工作中常见的是,字体资源暂未确定的情况下,先要进行UI的排版布局。待到后续字体资源确定后,再进行统一的更换。

但是单纯替换字体的方式异常繁琐,又容易遗漏,故而通过此脚本,创造一个EditorGUI,以进行一键更换字体

2.具体代码

using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEditor;
using UnityEngine;/// <summary>
/// 该脚本允许一键更换所有TMP_Text与TMP_InputField的字体
/// 包括场景及预制体
/// </summary>
public class ChangeFontWindow : EditorWindow
{/** MenuItem属性在编辑器上方创建了一个选项类* 默认的类有File, Edit, Assets, GameObject, Component, Window, Help七类*/[MenuItem("Tools/TMP_Text Fonts Change")]public static void Open(){/** GetWindow方法则直接打开了一个小窗口* 并调用其中的OnGUI方法*/GetWindow(typeof(ChangeFontWindow));}private TMP_FontAsset fontToChange;//这个作局部变量使用,用于保护静态变量被随意修改private static TMP_FontAsset m_fontToChange;private void OnGUI(){/**  EditorGUILayout.ObjectField生成了一个选项栏,允许给予特定的类型或资产*  其返回类型为Object,需要自己进行类型转换*/fontToChange =EditorGUILayout.ObjectField(fontToChange, typeof(TMP_FontAsset), true, GUILayout.MinWidth(100f))as TMP_FontAsset;m_fontToChange = fontToChange;/** GUILayout.Button方法绘制了一个按钮,按钮上的字符串便是参数中的值* 如果按下了按钮,则该值返回true,并随之调用设定好的函数*/if (GUILayout.Button("Change Fonts In Canvas")){ChangeInCanvas();}if (GUILayout.Button("Change Fonts In Prefabs")){ChangeInPrefabs();}}#region 修改场景中的字体private static void ChangeInCanvas(){TMP_Text[] tmpTexts = Resources.FindObjectsOfTypeAll<TMP_Text>();TMP_InputField[] tmpInputs = Resources.FindObjectsOfTypeAll<TMP_InputField>();foreach (TMP_Text text in tmpTexts){/** Undo.RecordObject用于记录场景中的物体的修改* EditorUtility.SetDirty用于记录预制体中的修改* 拓展内容见后续*/Undo.RecordObject(text, text.gameObject.name);text.font = m_fontToChange;EditorUtility.SetDirty(text);}/** 注意到,TMP_InputField下的TMP_Text是无法单纯更改其字体实现的* 需要修改TMP_InputField的参数才可以*/foreach (TMP_InputField input in tmpInputs){//同上Undo.RecordObject(input, input.gameObject.name);input.fontAsset = m_fontToChange;EditorUtility.SetDirty(input);}Debug.Log("Change font in canvas succeed!");}#endregion 修改场景中的字体#region 修改预制体中的字体private static void ChangeInPrefabs(){List<GameObject> prefabs = GetAllPrefabs();foreach (GameObject prefab in prefabs){TMP_Text[] texts = prefab.GetComponentsInChildren<TMP_Text>(true);TMP_InputField[] inputFields = prefab.GetComponentsInChildren<TMP_InputField>();foreach (TMP_Text text in texts){Undo.RecordObject(text, text.gameObject.name);text.font = m_fontToChange;EditorUtility.SetDirty(text);}foreach (TMP_InputField inputField in inputFields){Undo.RecordObject(inputField, inputField.gameObject.name);inputField.fontAsset = m_fontToChange;EditorUtility.SetDirty(inputField);}//使用新方法进行储存预制体PrefabUtility.SavePrefabAsset(prefab);}Debug.Log("Change font in prefabs succeed!");}/// <summary>/// 获取所有的预制体/// </summary>/// <returns></returns>private static List<GameObject> GetAllPrefabs(){List<GameObject> prefabs = new List<GameObject>();string resourcesPath = Application.dataPath;//利用C#自带的查找文件方式,查找该目录下所有包含该字符串的文件地址//位于System.IO命名空间下string[] absolutePaths = Directory.GetFiles(resourcesPath, "*.prefab", SearchOption.AllDirectories);for (int i = 0; i < absolutePaths.Length; i++){//如果数量比较多,有必要显示进度条EditorUtility.DisplayProgressBar("获取预制体……", "获取预制体中……", (float)i / absolutePaths.Length);/** 对于文件路径,斜杠及反斜杠的讨论* 见下*/string path = "Assets" + absolutePaths[i].Remove(0, resourcesPath.Length);path = path.Replace("\\", "/");GameObject prefab = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;if (prefab != null){prefabs.Add(prefab);}else{Debug.Log("预制体不存在! " + path);}}EditorUtility.ClearProgressBar();return prefabs;}#endregion 修改预制体中的字体
}

3.Undo与Dirty

这里只谈一下简要的介绍。

(1)Undo

Undo是将某个操作记入操作栈,便于后续撤销。例如,每次对场景中的组件、命名或其他内容有所改动时,Scene的图标上会出现一个*,表示该操作未保存,按下 Ctrl + S 之后,*消失,保存成功。但即使保存成功了,仍然可以通过 Ctrl + Z(Mac没用过,不晓得)的方式进行撤销。这就是因为我们的每一步操作都被记入了操作栈中。

Unity官方对Undo的介绍如下:

让您可以针对要执行更改的特定对象注册撤销操作。

撤销系统可以在撤销堆栈中存储增量更改。

系统会根据事件自动将多个撤销操作组合在一起,例如,根据鼠标按下事件拆分撤销组。分组后的撤销操作将作为单个撤销操作出现和使用。要手动控制分组方法,请使用 Undo.IncrementCurrentGroup。

默认情况下,系统将按照不同类型操作的硬编码顺序,从属于该组的各项操作中选择 UI 中显示的名称。要手动设置名称,请使用 Undo.SetCurrentGroupName。

撤销操作会存储每个属性或每个对象的状态。这样,如论场景的大小如何,它们都可以正确缩放。

最重要的几项操作如下所述:

修改单个属性:\ Undo.RecordObject (myGameObject.transform, "Zero Transform Position");myGameObject.transform.position = Vector3.zero;

添加组件:\ Undo.AddComponent<RigidBody>(myGameObject);

创建新的游戏对象:\ var go = new GameObject();Undo.RegisterCreatedObjectUndo (go, "Created go");

销毁游戏对象或组件:\ Undo.DestroyObjectImmediate (myGameObject);

更改变换组件的父子化:\ Undo.SetTransformParent (myGameObject.transform, newTransformParent, "Set new parent");

(2)Dirty

Dirty是一种标记,用来标记某个不需要撤销的操作(即该操作过后没有*,可以视为就是一个保存按钮?)。这是一种较为古老的方式,现在对于很多操作,官方已经不建议使用SetDirty方法,而改用上文的Undo去记录。

在许多给出的代码示例中,将二者混合使用,以达到修改后并保存的作用。

具体官方对SetDirty的方法介绍如下:

Marks target object as dirty.

You can use SetDirty when you want to modify an object without creating an undo entry, but still ensure the change is registered and not lost. If the object is part of a Scene, the Scene is marked dirty. If the object may be part of a Prefab instance, you additionally need to call PrefabUtility.RecordPrefabInstancePropertyModifications to ensure a Prefab override is created.

If you do want to support undo, you should not call SetDirty but rather use Undo.RecordObject prior to making changes to an object, since this will both mark the object as dirty (or the object's Scene if it is part of a Scene) and provide an undo entry in the editor. You should still also call PrefabUtility.RecordPrefabInstancePropertyModifications if the object may be part of a Prefab instance.

When you create editor UI for manipulating an object, such as a custom editor to modify serialized properties on a component or asset, if possible, you should use the SerializedProperty system using SerializedObject.FindProperty, SerializedObject.Update, EditorGUILayout.PropertyField, and SerializedObject.ApplyModifiedProperties. This will automatically mark the object as dirty, create an undo entry, and ensure Prefab overrides are created if relevant.

而在Prefab的处理中,参考了官方给出的建议,用 PrefabUtility.SavePrefabAsset(prefab) 方法对预制体的修改进行保存。

4.文件路径的斜杠与反斜杠

在网上看过不少文章,不同的作者对于符号定义不一致,看起来会略显混乱。故而在讨论之前,首先规定符号及名称的对应关系。纯属个人理解,不一定正确。

/,又称斜杠,正斜杠,左斜杠。就是键盘上跟?在一起的那个键。

\,又称反斜杠,右斜杠。就是键盘上在Enter上面的那个键。

在Linux, Unix系统上,均是使用 /(斜杠)分隔文件路径。

Windows系统上,起初 /(斜杠)用来表示DOS命令提示符的指令,为了便以区分,Windows采用 \(反斜杠)分隔文件路径。随着DOS的淘汰, /(斜杠)在Windows上也能够用以分隔文件路径。

        即,/(斜杠)适用于所有系统而 \(反斜杠)仅适用于Windows系统。

        由于Windows起初的规定,使得系统很多获取文件路径的结果都成了以 \(反斜杠)分隔。比如,Win11系统获取文件地址,可以右键菜单直接复制文件地址,粘贴出来之后得到的结果如下:

        "D:\Program Files\Unity\2019.4.36f1c1\Editor\Unity.exe"

        甚至还很贴心的加上了引号...

除此之外,使用 Directory.GetFiles 方法,得到的文件路径也是以 \(反斜杠)分隔。例如,该脚本放入任意Unity项目中,断点获取其路径的值,输出如下:

"E:/UnityLibrary/MyProjects/TestProject/Assets\\Addressables\\Prefabs\\DialogPanel.prefab"

        注意到,在前面用的还是 /(斜杠),而到了后面就变成了 \(反斜杠)。这是因为前面的路径,在代码中我们使用的是Unity的Application.dataPath,不妨理解,Unity为了更好地跨平台,使用了 /(斜杠)分隔,但是后续C#获取路径的方式又变成了获取Windows的路径,成了 \(反斜杠)。为了统一性,在代码中将所有的 \(反斜杠)统一替换成了 /(斜杠)。

        而具体的,是C#获取路径的结果就是 \(反斜杠),还是由于在Windows平台运行导致获取路径结果为 \(反斜杠)暂时不明。有兴趣的话不妨在其他系统上尝试一下。我个人倾向于是Windows系统的原因。

5.该脚本的修改与拓展

可以看到,我们可以对该脚本进行稍加修改,替换Text的字体;或者通过对背景Image添加Tag的方式,一键对所有的背景进行更换。实用性还是比较广的。

具体效果展示:

Unity一键更换TextMeshPro的字体相关推荐

  1. Unity 中 创建 TextMeshPro 中文字体(含常见汉字 TXT 文件)

    TextMeshPro是个好东西,但是原生不支持中文,需要把中文字体转换为TextMeshPro才可以使用,即创建TextMeshPro中文字体,为TextMeshPro添加中文支持.(文章内含 常见 ...

  2. TextMeshPro中文字体生成和字体材质更换

    TextMeshPro中文字体生成和字体材质更换 中文字体生成: TextMeshPro是unity提供的相较源Text更加强大,高效的字体组件.但其有一个严重的缺点就是默认不支持中文.所以我们需要制 ...

  3. win10字体安装_WIN10美化:一键更换系统字体!

    针对win10 的美化,小帮从未停止过,每天越来越多的时间都是坐在电脑面前,面对一个自己精心改造的桌面不仅仅可以提高我们的工作效率,心情也会变得美美哒. 今天我们就来聊聊如果更改win10系统的字体. ...

  4. Unity学习笔记 关于TextMeshPro(TMP) 字体大小FontSize单位说明

    前言 一般表示字体大小使用的单位分两种方式表示:pt(磅)和px(像素). pt:是指一个印刷单位"磅",大小为 1/72 英寸,是一个自然界标准的长度单位,也称为"绝对 ...

  5. Unity一件替换所有字体Font

    网上看到一个方法 但是此方法的弊端是当父物体隐藏后就无法在替换字体了,对此改进了一下,通过递归每个父节点的子物体来进行替换可以解决 链接地址:Unity 一键快速换字体,告别一个个的手动更改_Liam ...

  6. linux系统更新字体,更换Linux下字体

    我的Linux系统是Ubuntu 14.04,更换完字体之后,Web页面效果是这样的: Shell显示效果是这样的: 我采用的字体方案是,Monaco雅黑混合字体 下面是具体更换步骤: 一.下载安装字 ...

  7. 主题图标_iPhone一键更换主题、图标神器

    iOS图标虽然是经典,但是看久了也是会腻的.今天教大家一个简单的方法,来更换iPhone的图标. 更换主题.图标教程 前往App Store搜索[moloko]进行下载安装,这是一款可以替iPhone ...

  8. python更换国内源_一键更换国内云服务器Python pip镜像源至国内Pypi镜像源

    前言 为了更方便的为国内的服务器更换Python pip源(就是懒,特别是最近),特意写了一个一键更换pip源脚本,目前只在Centos上测试过,不过理论上Linux系统通用 使用 Centos/De ...

  9. Manjaro更换系统默认字体,主题

    Manjaro如何更换系统默认字体呢? 1.打开设置,直接查找 "外观",如下图 2.可见下图 3.样式,图标,字体等都可以设置,下载网上一些主题,进行更换吧!

  10. Python一键更换证件照背景色

    Python一键更换证件照背景色 PS: 也是从网上各个帖子中学习的Python,因此代码的格式以及内容有粘贴网上其他大神的代码,如有侵权请告知删除 示例界面 import cv2 import nu ...

最新文章

  1. 一个一元二次方程求解编程引申的两个知识点(abs和fabs的区别以及浮点数比较相等)...
  2. 非聚集索引和聚集索引
  3. append 降低数组位数_4.有序数组
  4. SAP Spartacus里的标准Banner设计
  5. openssl里面AES算法主要函数的参数的介绍
  6. MyBatis-Plus_实体作为条件构造器构造方法的参数
  7. 【源码解读】EOS测试插件:txn_test_gen_plugin.cpp
  8. 必须声明标量变量 @列名
  9. HDU3709 Balanced Number
  10. 华为HCNA好考吗?
  11. 计算机系统确认的gmp附录,马义岭--中国GMP 附录确认与验证计算机化系统.pdf
  12. pdca实施的流程图_思维导图丨《高效PDCA工作术》流程图
  13. 苹果官方付费升级内存_32GB内存秒变64GB ,vivo官方推出内存升级服务
  14. 输出1234无重复三位数
  15. 孤独者的自我救赎[自我的认知]
  16. After Effects快捷键
  17. 微信朋友圈+html+字体颜色,改变微信聊天字体颜色的方法?
  18. Spring Cloud Gateway — 网关基本功能API暴露
  19. 计算机的cut代表什么意思,cut是什么意思_cut在线翻译_英语_读音_用法_例句_海词词典...
  20. coreldraw铺花纹_CorelDRAW打造漂亮剪纸花纹教程

热门文章

  1. jquery 内容分页_为内容创建现代jQuery分页
  2. layui 模板使用
  3. word文档插入尾注,并且设置尾注在参考文献这一章
  4. ERP实用技巧:物料清单编制------(转)
  5. python中英文对齐_Python中英文对齐终极解决方案
  6. gxf------阿里云学生机部署Django项目2020
  7. ARM裸机--看门狗定时器
  8. 巴菲特致股东的信pdf_巴菲特历年股东大会股东信问答实录集合(共7份)
  9. 电商直播发展正夯,云计算技术硬核支撑
  10. QQ邮箱收不到GitHub验证邮件