Unity 游戏汉化之 TMP 字体替换
当 Unity 游戏用了 TMP 之后由于 Font Atlas 是预先生成的, 导致不存在的字体则会出现 口口口 的现象。这边阐述一个相对简单的思路来替换字体。
- 下载同版本的 UnityEditor
- 建立项目后安装同版本的 TextMeshPro
- 使用 TextMeshPro 建立字体并且打包 AssetBundle
- Hook TMPro.TextMeshProUGUI 类中的 OnEnable 方法, 并实现如下类似逻辑:
using System;
using System.IO;
using MonoMod;
using TMPro;
using UnityEngine;
namespace TMPPatch
{
[MonoModPatch("global::TMPro.TextMeshProUGUI")]
public class TMPText
{
extern void orig_OnEnable();
private static TMP_FontAsset maruFont = null;
private static TMP_FontAsset boldFont = null;
protected void OnEnable()
{
if (maruFont == null || boldFont == null)
{
var fontPath = Path.Combine(Environment.CurrentDirectory, "majbridge", "chinese_font");
if (File.Exists(fontPath))
{
var ab = AssetBundle.LoadFromFile(fontPath);
maruFont = ab.LoadAsset<TMP_FontAsset>("SweiGothicCJKsc-Regular SDF");
boldFont = ab.LoadAsset<TMP_FontAsset>("sgm SDF");
if (maruFont.characterLookupTable == null)
maruFont.ReadFontAssetDefinition();
if (boldFont.characterLookupTable == null)
boldFont.ReadFontAssetDefinition();
Console.WriteLine("[MajBridge TMP] Loaded font");
}
}
if (maruFont != null && boldFont != null)
{
var _this = (TextMeshProUGUI)(object)this;
var material = _this.fontMaterial;
_this.font = boldFont;
if (material != null)
{
material.SetTexture(ShaderUtilities.ID_MainTex, boldFont.atlasTexture);
_this.fontMaterial = material;
}
}
orig_OnEnable();
}
}
}
注: 其中备份 material 并且再设置完字体之后替换回去是为了保留字体的描边等效果, 由于 TMPro 中实现这些完全效果由着色器实现, 参数定义在 Material 中, 所以这么做就可以保留文字效果。