版本:UE 5.1

前言

为什么要有这篇文档?

在项目开发中,我们常常需要生成一些数字标牌,可能是静态的也有可能要始终面朝摄像机。通常我们会在actor上面挂载一个控件或者使用文本渲染actor,但是这样比较繁琐也会消耗大量性能,这个组件就提供了一种方法去完善这样的问题,本文提供了两种方案,它们的具体思路相同,只是依靠的底层渲染有差异【ISM和Niagara】,可以看我下面的详细介绍

image
image


一、整体架构设计

本插件将“数字展示”拆解为三层逻辑,简单来说就是:

蓝图负责传参和调用,材质负责拿到单个字符贴图,Niagara/ISM负责渲染。


二、各方案核心组件与关键变量

Niagara_Mesh:

image
image

相关文件夹内容

组件名称 类型 职责描述
BP_NiagaraMesh Actor Niagara数字载体。内部调用Add Nums_Mesh

函数生成数字。注:最初尝试Sprite(精灵)渲染器,因不支持三轴旋转,最终定为Mesh(网格体)渲染器。
S_Mesh 结构体(Struct) 数据传输结构体,用于打包传入Niagara的数字数组。

image
image

相关函数

Niagara 生成函数,核心函数(Add Nums_Mesh),平时使用只需要调用这个函数即可

  • 所属:BP_NiagaraMesh
  • 传参说明:需传入数组(Array)。
  • 字体更换:在细节面板修改材质实例,或直接打开材质实例替换字符集贴图。

注意:两个方案的字体切换都是依靠的相关材质,这里如需更换字体仅需要生成新的字体的字符集替换到材质实例即可,这里我做了一个脚本,可以直接生成字符集贴图。

image
image
image
image
当前actor蓝图使用编辑器中调用自定义函数(自动生成)

image
image

S_Mesh数组参数

关键变量映射表(Niagara结构体细节面板):

变量名(面板显示) 变量名(底层) 功能说明
字体(Text) Material Instance 通过更换材质实例或字符集贴图切换字体。
位置(Location) Position 控制数字在场景中的绝对位置。
字体颜色(Color) Color 控制数字显示颜色。
背景颜色(BackGround) Background Color Niagara独有,支持为数字添加背景板。
尺寸(Size) Scale 控制数字大小。
旋转(Rotation) Rotation 支持三轴旋转(Pitch, Yaw, Roll)。

ISM:

ISM 生成函数(Add Numbers),平时使用只需要调用这个函数即可

  • 所属:BP_ISMNum
  • 传参说明:直接传入数字数据。
  • 字体更换:仅支持在材质实例中替换字符集贴图(暂时不支持背景颜色,材质里面也能改,后续会完善)。

image
image

相关函数

image
image

当前actor蓝图使用编辑器中调用自定义函数(自动生成)

image
image

相关文件夹内容

组件名称 类型 职责描述
BP_ISMNum Actor ISM数字载体,挂载ISM组件。内部调用Add Nums
S_Mesh 结构体(Struct) 数据传输结构体,用于打包传入Niagara的数字数组。

image
image

S_ISM数组参数

关键变量映射表(Niagara结构体细节面板):

变量名(面板显示) 变量名(底层) 功能说明
字体(Text) Material Instance 通过更换材质实例或字符集贴图切换字体。
位置(Location) Position【5.1ueNiagara用位置数组,不用向量数组】 控制数字在场景中的绝对位置。
字体颜色(Color) Color 控制数字显示颜色。
尺寸(Scale) Scale【5.1ueNiagara用位置数组,不用向量数组】 控制数字大小。
旋转(Rotation) Rotation 支持三轴旋转(Pitch, Yaw, Roll)。

备注:ISM方案也可以加上背景板,只是当前还没在材质里面写,底层逻辑和Niagara都是一套的

三、函数具体介绍

这里以Niagara为例介绍,因为他们的实现逻辑都是一样的

Build Pack-字符打包

image
image

PackedAB——打包再次处理【这个仅Niagara方案的这个蓝图有】

因为这里传给Niagara的PackA(B)是数组,所以需要打包一下再传入【这里比ISM多一个这个函数】

image
image
Add Numbers——核心函数,主要是把数据的数组传给Niagara的用户参数,这些用户参数绑定了Niagara里面我创建的一个本地模块,这个本地模块会把传入的数组数组解析成单个的,然后传给粒子属性去渲染【这里ISM就不用传这些数组了,直接把数据给到ISM的属性节点(设置自定义数据值节点)去成实例化网格体即可】

image
image

image
image

补充:ISM里面使用了一个数学表达式去简化计算

四、性能基准与选型建议(核心)

基于 UE 5.4 环境下生成 50,000 个数字的压力测试数据如下(Niagara采用CPU模拟):

性能指标 ✅ 方案一:Niagara 网格体渲染器 ❌ 方案二:ISM 实例化
总帧耗时 8.64 ms(≈116 FPS) 24.38 ms(≈41 FPS)
Game线程 7.91 ms 8.79 ms
渲染线程(Draw/Render) 5.68 ms(优秀) 24.04 ms(严重瓶颈)⚠️
GPU耗时 6.56 ms(优秀) 23.72 ms(过载)❌
Draw Call 数量 232 242
三角面数(Prims) 7,963(极低) 108,100(过高)❌
是否达到 60 FPS ✅ 是(远超标准) ❌ 否

选型建议:

  • 数量 > 1W 的海量数字:强制使用 Niagara 网格体渲染器。其在渲染线程和GPU上的优化极佳,三角面数仅为ISM的十分之一。
  • 少量数量数字:两者性能差距可忽略,ISM方案因逻辑简单、无需拖拽Niagara资产,可作为快速原型选择。
  • 特殊需求:若需要**“始终面向摄像机”或“独立背景颜色”,Niagara方案为唯一解**(ISM目前均不支持,但是其实也可以修改,因为两套的实现逻辑是一样的)。
  • 【提示】可以在 Niagara 里设置数字 始终面向摄像机,就去相关的Niagara细节面板里面,找到朝向模式进行调整

五、标准使用流程

路径一:Niagara 方案(高性能、可视化效果强)

  1. 将 BP_NiagaraMesh 拖入场景。
  2. 在细节面板调整好字体、颜色、大小、旋转等默认参数。
  3. (关键步骤) 点击细节面板中的 【自动生成】 按钮,系统即根据预设参数生成数字粒子。

image
image

路径二:ISM 方案(轻量级、快速展示)

  1. 将 BP_ISMNum 拖入场景。
  2. 设置好细节面板中结构体里里面的参数

image
image


六、调试与常见问题

  • Q:生成的数字不显示或显示为乱码?
    A:检查传入的字符是否在当前字符集(0~9,".","%"等)范围内,并确认材质实例中的字符集贴图排列顺序与代码映射逻辑一致。
  • Q:Niagara 生成的数字无法实现三轴旋转?
    A:请确认使用的是 网格体渲染器(Mesh Renderer) 而非精灵渲染器(Sprite Renderer)。本来我最初是用的的精灵渲染器,但是因为精灵渲染器不支持三轴旋转,所以换成了网格体渲染器,本来我是做的5.4版本的,后来改到5.1去做发现Niagara里面网格体渲染器的粒子index和5.4版本的不一样,以及5.1版本中Niagara最好不要使用向量数组(似乎有bug)而改用位置数组
  • Q:如何在Niagara中让数字始终面向摄像机?
    A:选中Niagara组件,在细节面板中找到 “朝向模式(Facing Mode)”,将其设置为“面向摄像机(Face Camera)”即可。
  • 具体见下图

image
image

补充:新写了一个编辑器工具测试两个方案大量生成数字的性能

image
image