如何让表情符号显示在 Unity TextMeshPro 元素中?

Mas*_*han 7 c# unicode unity-game-engine tweets emoji

我似乎在网上找不到任何关于这个主题的帖子或视频,所以我开始怀疑这是否不可能。Unity 中有关“表情符号”的所有内容都只是 spritesheet 的简单实现,然后使用 like 手动索引它们<sprite=0>。我正在尝试从 Twitter 中提取推文,然后使用表情符号显示其文本,因此显然这对于​​ unicode 支持的 1500 多个表情符号来说是不可行的。

我相信我已经使用默认的 Windows 表情符号字体 Segoe UI Emoji 正确创建了 TMP 字体资源,并且看起来使用我在在线 unicode 数据库上找到的一些 unicode 十六进制范围,我能够在字体中检测到 1505 个表情符号。 成功创建表情符号字体

然后,我在项目设置中将表情符号字体设置为后备字体: 将表情符号字体设置为后备

但运行游戏后,我仍然遇到同样的错误The character with Unicode value \uD83D was not found in the [SEGOEUI SDF] font asset or any potential fallbacks. It was replaced by Unicode character \u25A1 in text object

在控制台中,推​​文文本的输出如下所示:#cat #cats #CatsOfTwitter #CatsOnTwitter #pet \nLike &amp; share , Thanks!\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F

从网上的一些资料和 unicode 的基本知识来看,我推测问题是在推文正文中,表情符号采用 UTF-16 代理对或其他形式,其中\uD83D\uDE4F一个表情符号在哪里,但我的表情符号字体是 UTF-32 ,所以它正在寻找u+0001f64f. 那么我是否需要找到一种方法让它读取完整的代理对,然后转换为 UTF-32 以获取要渲染的正确表情符号?

任何帮助将不胜感激,我尝试询问 Unity Discord 服务器,但没有其他人知道如何解决这个问题。

MrD*_*ond 4

介绍

\n

TMPro 本身就能够执行此操作,但仅限于 UTF-32 格式的 unicode。例如,\\U0001F600是\'\xef\xb8\x8e\'。你的表情符号的格式是 UTF-8(如果我错了,请纠正我),\\u1F600仍然是 '\xef\xb8\x8e\'。两者之间的唯一区别是大写字母U和前面的 3 个零。这使得转换非常容易。在 TMPro 中输入 UTF-32 版本会正常显示表情符号。您正在寻找的是将 UTF-16 代理对转换为 UTF-32,这将在下面进一步介绍。

\n

幸运的是,这个解决方案不需要任何字体修改,默认字体就可以做到这一点,而且我没有更改检查器中的任何设置。

\n

UTF-8解决方案

\n

下面的解决方案适用于非代理对 UTF-8 代码。

\n

要将 UTF-8 转换为 UTF-32,我们只需将“u”更改为大写并在其前面添加几个零即可。为此,我们可以使用System.RegularExpressions.Regex.Replace.

\n
public string ToUTF32(string input)\n{\n    string output = input;\n    Regex pattern = new Regex(@"\\\\u[a-zA-Z0-9]*");\n\n    while (output.Contains(@"\\u"))\n    {\n        output = pattern.Replace(output, @"\\U000" + output.Substring(output.IndexOf(@"\\u", StringComparison.Ordinal) + 2, 5), 1);\n    }\n\n    return output;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

input是包含表情符号 unicode 的字符串。该函数转换字符串中的所有 unicode,并保持其他所有内容不变。

\n

解释

\n

这段代码很长,所以这就是解释。

\n

首先,代码获取输入字符串,例如 ,blah blah \\u1F600 blah \\u1F603 blah其中包含 2 个 unicode 表情符号,并将 unicode 替换为另一个长字符串代码,这是下一节。

\n

其次,它接受输入并Substring保存“\\u”之后的所有内容,前面 5 个字符。它将文本替换为"\\U000" + the aforementioned string.

\n

它重复上述步骤,直到翻译完所有 unicode。

\n

这会输出正确的字符串来完成这项工作。

\n

如果有人认为上述信息不正确,请告诉我。我在这个主题上的词汇不是最好的,所以我愿意接受指正。

\n

代理对解决方案

\n

我修改了一段时间并提出了下面的功能。

\n
public string ToUTF32FromPair(string input)\n{\n    var output = input;\n\n    Regex pattern = new Regex(@"\\\\u[a-zA-Z0-9]*\\\\u[a-zA-Z0-9]*");\n\n    while (output.Contains(@"\\u"))\n    {\n        output = pattern.Replace(output, \n            m => {\n                var pair = m.Value;\n                var first = pair.Substring(0, 6);\n                var second = pair.Substring(6, 6);\n                var firstInt = Convert.ToInt32(first.Substring(2), 16);\n                var secondInt = Convert.ToInt32(second.Substring(2), 16);\n                var codePoint = (firstInt - 0xD800) * 0x400 + (secondInt - 0xDC00) + 0x10000;\n                return @"\\U" + codePoint.ToString("X8");\n            }, \n            1\n        );\n    }\n\n    return output;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这与之前的操作基本相同,只是它接受其中包含代理对的输入并对其进行翻译。

\n

表情符号和检查员

\n