多语言字体与 CJK 支持
多语言文本动画的核心挑战在于 CJK(中日韩)字符的正确分割与 Unicode 码点处理。Texturge 通过 FCharBreakIterator、Texturge::Unicode 工具与码元/字形双向映射解决这些问题。
NOTE
Texturge 不存在
UTexturgeFontAsset、字体图集烘焙或 SDF 字形缓存。字符渲染由 UMG/Slate 的标准字体管线处理,插件仅负责动画曲线逻辑与字形分割。
字形分割管线
为什么需要特殊处理
- CJK 文本不使用空格分词,每个字符独立表意
- UTF-16 码元(TCHAR)不等于 Unicode 码点:Emoji 等增补平面字符由代理对(2 个码元)组成
- 逐字形动画必须以码点为单位,而非码元
FCharBreakIterator
FCharBreakIterator 实现 IBreakIterator 接口,在 SetString 时预计算全部断点:
// 实现 IBreakIterator 接口
FCharBreakIterator Iterator;
Iterator.SetString(InText); // 预计算断点数组(含 0 与末尾)
int32 Pos = Iterator.ResetToBeginning();
while ((Pos = Iterator.MoveToNext()) != INDEX_NONE)
{
// 每个断点 = 一个字形边界
}
主要能力:
- 代理对安全——增补平面字符(Emoji 🎮 等)作为一个字形,不分裂
- CJK 附着——CJK 标点正确归属(
IsCJKPunctuation) - 韩文音节——谚文音节块作为整体处理
GetCurrentPosition()/MoveToPrevious()/MoveToCandidateBefore/MoveToCandidateAfter完整游标接口
码元 ↔ 字形双向映射
UTextAnimator 维护两个映射数组(0.2.0 引入,全文按码点索引统一):
| 映射 | 说明 |
|---|---|
CodeUnitToGlyphIndex | 码元索引 → 字形索引(代理对两码元映射同一字形) |
GlyphIndexToCodeUnit | 字形索引 → 码元索引 |
GetGlyphIndexForCodeUnit(int32) 公开查询接口。打字机揭示、富文本段落截取(SerializeSubstring)均按码点索引工作。
与传统方法对比
| 方法 | 拉丁字符 | CJK | Emoji(代理对) |
|---|---|---|---|
| 按 TCHAR(UTF-16 码元)切分 | 正确 | 正确 | 错误(分裂为 2 字形) |
| 按字节切分 | 错误 | 错误 | 错误 |
FCharBreakIterator + 码点索引 | 正确 | 正确 | 正确 |
Unicode 工具类
Texturge::Unicode 命名空间提供码点级分类函数(UnicodeUtils.h,全部 FORCEINLINE):
| 函数 | 判定范围 |
|---|---|
IsCJKUnifiedIdeographs(uint32) | 主区块 + 扩展 A~F/I + 兼容表意(0x3400-0x2FA1F) |
IsHiragana(uint32) | 平假名 0x3040-0x309F |
IsKatakana(uint32) | 片假名 0x30A0-0x30FF、0x31F0-0x31FF |
IsHangulSyllables(uint32) | 谚文音节 0xAC00-0xD7AF、谚文字母 0x1100-0x11FF |
IsCJKPunctuation(uint32) | CJK 标点 0x3000-0x303F、0xFE30-0xFE4F、0xFF01-0xFF60、0xFFE0-0xFFEE |
IsCJK(uint32) | 以上五者聚合 |
IsHighSurrogate(TCHAR) / IsLowSurrogate(TCHAR) | UTF-16 代理区判定 |
ComposeSurrogatePair(TCHAR, TCHAR) | 代理对合成 32 位码点 |
这些工具在 BuildScheduleInfos 中用于分类每个字形(bIsWhitespace / bIsPunctuation / bIsCJK / bIsDecorator),决定其调度行为。
字体回退
Texturge 不直接管理字体资产,依赖 UMG 字体管线:
- 在
UAnimatedTextBlock/UAnimatedRichTextBlock的Font属性(继承自基类)设置主字体 - UE5 复合字体(Composite Font)系统自动处理缺失字符回退
- 覆盖多语言的复杂场景,使用复合字体的子字体(Sub-Font)功能分别指定各书写系统的字体
TIP
对于覆盖多语言的项目,使用复合字体的子字体功能分别为各书写系统指定字体,而非依赖多控件叠加。
测试 CJK 动画
推荐测试文本
在 STextAnimationDesignerView 的预览文本框(UTexturgePreviewSceneConfig::PreviewText)输入以下混合文本验证支持:
English 日本語 한국어 中文 العربية हिन्दी
Emoji: 🎮🎯✨
全角:ABCD1234
验证检查项
- 字形计数正确——每个 CJK 字 / Emoji 计为一个字形(代理对不分裂)
- 调度延迟均匀——逐字动画节奏不因字符编码长度变化而跳帧
- 分类正确——空白 / 标点 / CJK / 装饰器分类在
BuildScheduleInfos输出中正确 - RTL 文本——阿拉伯文从右到左正确排列(布局由 Slate 处理)