【发布时间】:2023-02-20 14:46:54
【问题描述】:
我正在做一个传统的 roguelike 项目。我有一个玩家日志,显示发生了什么,玩家移动到这里,机器人攻击玩家,玩家施放能力等。这是相当有用的信息并且它经常更新,每次玩家采取行动时至少会生成一行,如果有周围有任何敌人,它们也会产生线条。
我正在使用包裹在滚动矩形内的视口内的 TMP 来显示日志的最后 10 行左右,滚动矩形使我们能够向上滚动以查看之前的行。
最初,我会天真地向 TMP.text 添加行,这只会增长,但是,我很快注意到性能问题,无论何时附加文本,TMP.GenerateTextMesh/GenerateText 调用都会迅速增加到明显变慢的程度游戏下来一百行左右。
所以为了部分解决这个问题,我现在将日志的文本存储在一个旋转的循环缓冲区中,并在 TMP.text 中只保留 20 行左右,这使得性能很好。但是当添加新行或用户滚动查看旧行时,该 .text 值仍然需要更改。即使文本量相对较少,大约 20 行,对 TMP.GenerateText 的调用也需要大约 10 毫秒(启用深度分析器),这对于相对简单的 UI 来说是一个疯狂的成本。成本是每次更新,所以一旦制作了文本,渲染成本就很低,但如果你有一个经常变化的文本字段,成本就会过高。
是否有更好的解决方案来显示内容频繁更改的动态文本字段?我想任何有聊天客户端的东西都会面临类似的问题,所以必须有一个解决方案。
【问题讨论】:
-
通常,聊天客户端对一个对话使用一个文本元素。你可以做类似的事情,比如一行一个文本,然后将它们放在一个布局组中。
-
anything with a chat client通常不会使用 3D 游戏渲染引擎来显示聊天客户端。数百行确实是一个大问题,因为 TMP 基本上必须将所有这些转换为带有顶点的 3D 网格,然后进行渲染。 Unity 应用程序并不是真正为处理和显示大量文本而设计的。一种方法可能是简单地不更新每一帧的文本显示,而是允许每 3 秒左右出现一次尖峰并定期更新显示 -
偶尔损失 10 毫秒听起来确实没那么糟糕。也就是说,连接字符串是一个非常慢的操作——这是“循环缓冲区”在做什么吗?如果是这样,请尝试使用
Stringbuilder。 -
战斗日志中的 3D 文本对我来说有点矫枉过正,为什么不使用标准的光栅字体呢?它比渲染 3D 文本要快得多,而且我认为您会发现 MMORPG 无论如何都会这样做。
-
感谢 cmets。有几点需要澄清。连接字符串已经用 stringbuilder 完成了,这不是减速的根源。减速的原因是 TMP 重建顶点以呈现新的文本数据。文本不是 3D 并且渲染时间不是问题,它可以快速渲染。问题是重建时间。 TMP 不会重建每一帧,它只会在有新输入时重建,但是,我喜欢将新文本批处理 1000 毫秒左右的想法,以防有多个按键,+1 derHugo。
标签: unity3d textmeshpro