ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

UE4 UMG九宫格拉伸:彻底解决UI图片变形难题

UE4 UMG九宫格拉伸:彻底解决UI图片变形难题 1. 素材准备与九宫格切分原理1.1 UI拉伸变形的老大难做UE4项目界面的时候大家应该都遇到过这种情况美术给了一张精致的按钮底图边框带有渐变光泽四角还有圆角和装饰线条。放到UMG里一拉伸整个图片变形得没法看——圆角被拉成了椭圆描边粗一条细一条渐变糊成一团。辛辛苦苦调的界面换个分辨率或者适配不同屏幕比例直接翻车。这个问题困扰了UI开发者很多年。早期做法是让美术出多套不同尺寸的切图界面一改就要重新切图效率极低。后来有了九宫格拉伸也叫9-slicing、scale9从根本上解决了“图片拉伸不变形”的难题。在UE4里配合UMG的Image控件我们可以用非常简洁的方式实现任意尺寸的UI背景而且只需要一张素材图。1.2 九宫格的核心原理九宫格方案的核心思想其实非常朴素把一张图用两条水平线和两条垂直线切成9个区域3x3网格4个角部区域始终保持原始尺寸不做任何缩放。4条边区域只在单一方向上拉伸上下边横向拉伸、左右边纵向拉伸。1个中心区域横竖两个方向都可以拉伸。这样一来无论目标控件被拉伸到多大圆角、描边、阴影这些“关键视觉元素”都被固定在四个角上绝对不参与缩放中间的纯色或纹理部分被拉伸视觉上基本无感。这里用大家都熟悉的例子类比你想把一个窗框放大如果整块玻璃连带边框一起变大玻璃上的花纹会变形但如果只把中间玻璃区域拉伸四角的木质边框保持原样放大后的窗户依旧协调。九宫格做的就是这件事。UE4的UMG里实现九宫格操作非常直接。选中Image控件后在细节面板找到“Draw As”选项从默认的Image切换为“Border”模式然后调整“Margin”参数即可。UI开发新手往往卡在这一步因为不知道这个参数怎么填填错了效果也很奇怪。2. 图片资源要求与九宫格关键设置2.1 美术资源的正确导出方式先说资源的规范。九宫格对原图的尺寸和内容分布有明确要求美术出图前就要沟通好否则后期调起来很痛苦。一张适合做九宫格的底图建议满足以下条件尺寸不要太小最好在256x256像素以上。因为安全区四周边框区域需要保留足够的像素来呈现圆角、渐变、纹理细节如果切图只有32x32放大之后角部区域也会模糊。图片四周的圆角、描边、装饰性元素要均匀分布在边缘附近不要在中心区域搞太多花纹因为中心区域会被拉伸甚至平铺。建议导出时在四边各留出明确的“边框保护区域”比如按钮底图四边各留24~48像素的纯色或渐变区域不要把需要保持比例的元素溢出到中心区。格式方面UE4支持TGA、PNG、JPG等UI建议优先用PNG或TGA保留透明通道。JPG不支持透明做圆角按钮白底会露馅。在UE4的内容浏览器中选中贴图细节面板勾选“sRGB”MipGen设置为“NoMipmaps”或“FromTextureGroup”。UI贴图不要开mipmap否则缩小时会模糊放大时也可能出现奇怪的颜色渗边。2.2 Draw As与Margin参数详解在控件蓝图中放置一个Image选中它右侧细节面板的Appearance分类下找到“Draw As”。这个选项决定Image以何种方式渲染常见的有Image普通图片拉伸四个角跟着变最容易变形。Border九宫格模式就是我们需要的。Box带九宫格边界的盒状模式。Background平铺背景模式。选择Border后下方会出现“Margin”属性这里填的就是九宫格四条分割线的位置顺序是Left、Top、Right、Bottom单位是像素。这四个值的含义分别是左侧边界的切分位置、上侧边界的切分位置、右侧边界的切分位置、下侧边界的切分位置。注意它不是留白的意思而是控制“角部区域”的宽度和高度。举个例子如果原图大小是256x256四角的圆角半径大约36像素那么Margin可设置为Left36、Top36、Right36、Bottom36。这样九个区域中左上角就对应图片左上角0~36像素范围内的区域其他角同理。分割线内部的中央矩形就是可变区域。Margin四个值如果不等也能实现非常规分割例如只希望左右拉伸、上下固定就把Top和Bottom设为0。反过来如果希望角部区域大一些比如长阴影按钮调大对应的Margin值即可。2.3 Draw As设为Border后的容易被忽略的渲染细节切到Border模式后有几个渲染细节值得留意当目标图片尺寸小于Margin设定值时UE4不会报错但显示效果可能出现奇怪的重复或拉伸尽量避免这种情况。九宫格模式下贴图的Wrap模式建议设置为Clamp而不是Repeat否则边部区域容易出现重复采样导致的规律条纹。在Border模式下Image的“Color and Opacity”的透明度调整仍然有效可用来制作按钮的按下/悬停反馈不需要额外准备多套贴图。如果贴图带有很宽的渐变色比如上深下浅、左右有亮边拉伸后中心区域渐变会过渡得比较自然但边部和中心交界处偶尔会看到一条微弱的接缝。这个现象在移动端比较常见原因在于边部贴图的UV映射到整数像素后产生了半像素采样偏差。解决办法是让美术把中心区域做成纯色或者非常缓的渐变尽量在视觉上平滑过渡。3. 在UMG控件蓝图中配置九宫格图片3.1 创建控件蓝图并放置Image下面进入实操环节。我这里假设你已经有一个工程里面放入了一张UI底图命名为“BG_Button”。现在要创建一个带九宫格的UI控件。步骤一在Content Browser中右键选“用户界面”→“控件蓝图Widget Blueprint”父类选“UserWidget”命名为“WBP_ButtonTest”。步骤二双击打开WBP_ButtonTest在设计器左侧的Palette面板中找到“Image”拖入画布中。调整Image的锚点和偏移让它在画布上覆盖一定区域。为了直观看到九宫格效果可以先把Image的尺寸拉大到控件的一半。步骤三选中Image在细节面板中点击“Appearance”展开“Draw As”改选为“Border”。步骤四在“Margin”对应的Left、Top、Right、Bottom中输入之前设计好的数值。对应示例图256x256边框36像素所以填入36、36、36、36。步骤五把“Brush”右侧的“Image”引用设置为BG_Button贴图。设置好之后运行界面拖动Image控件的大小你会发现四个角的圆角完全不变形中间区域被拉伸填充了。3.2 通过蓝图动态调整九宫格Margin很多场景下Margin不能写死在细节面板里。比如启动时根据屏幕分辨率自动调整角部大小或者根据不同的状态切换不同圆角样式。这时候就需要通过蓝图动态设置。在蓝图图表中通过GetWidgetFromName或者直接引用变量拿到Image控件然后调用“Set Brush Margin”节点全称SetBrushMarginWithIdentity或SetBrushMargin视引擎版本略有不同。这个节点需要传一个Margin结构体在蓝图中右键搜索“Make Margin”就可以展开Left、Top、Right、Bottom四个输入。实际项目里我常用这种动态调整来做主题换肤功能不同主题的按钮底图圆角弧度不一样通过动态Set Brush Margin可以在不切换控件的情况下适配多套底图。只需要在初始化时根据当前皮肤ID设置一组对应边距参数即可。这里有一个需要注意的点动态调用Set Brush Margin后Image的Draw As必须保持在Border模式否则节点虽然执行渲染效果不会变化。如果从Image切到Border后忘记在细节面板确认代码逻辑正确但画面没变化会让人排查半天。3.3 九宫格在列表项与动态大小场景中的配合九宫格最实用的场景其实是配合可变尺寸的容器。比如一个聊天消息框文本长度不确定消息背景框的尺寸需要跟着文本增长或者背包格子的背景格子大小需要适配不同物品数量的面板。在控件蓝图中创建一个名为“WBP_ChatBubble”的UserWidget内部结构如下根节点Canvas Panel。放置一个Border控件注意这里的Border是容器控件不是Image控件的Draw As模式撑满整个画布。在Border中嵌套一个TextBlock显示聊天文字内容。选中Border控件会在细节面板看到背景相关的“Brush”设置。这里同样可以把Brush的Draw As设为Border然后指定贴图和Margin。当TextBlock的内容很多时Border会自动撑开背景图片的九宫格效果也会跟随尺寸的变化动态渲染。这个方式比在蓝图中手动计算控件大小再设置Image尺寸要省力得多而且天然适配各种文本长度。顺带说一下UMG的Border容器自带的Brush绘制机制和Image本质上是一样的都是Slate的BorderBrush。所以你可以把Border当作“带九宫格背景的容器”来用。后续如果需要调整Padding只需要在Border的Padding属性中设置让文字离背景边缘有一定的间距视觉上就会非常自然。4. 进阶玩法动态尺寸按钮与动画配合4.1 可自动扩展的按钮状态项目中经常需要“根据文案长度自动调整宽度”的按钮。做本地化时中英文长度差异巨大英文按钮可能比中文长一倍。传统切图方案需要准备多套图片或者强制限制最大宽度。使用九宫格之后按钮底图只需要一张。此时按钮的根节点建议用SizeBox或Horizontal Box让内容自适应。然后在按钮的Background控件中设置九宫格背景。当Content文本的长度变化时Background会自动扩展边角始终保持清晰。如果想在蓝图中获取计算后的按钮实际宽度比如需要让另一个控件对齐可以绑定一个事件在OnPaint或OnTick中读取按钮控件的DesiredSize。不过要注意时序问题文本修改后DesiredSize并不会立刻更新要等到下一帧布局重新计算后才能拿到正确值。遇到这类问题可以把读取逻辑延迟一帧执行或者使用“PreConstruct”事件在编辑器里预览。4.2 为九宫格图片添加悬停/按下动效利用九宫格还可以做到一个素材实现多种交互状态方法有二方法一通过Color and Opacity改变颜色。九宫格中心区域如果是白色或浅色可以设置Image的Color属性来着色。制作悬停时变成高亮色按下变成暗色。这种方式特别适合做扁平风格按钮缺点是不能改变描边颜色之外的纹理细节。方法二动态替换Brush贴图。在蓝图按钮的OnHovered事件里使用SetBrushFromTexture换上另一张九宫格贴图离开时再换回原图。这种做法在MMORPG的宝石镶嵌槽、技能按钮等需要高对比反馈的场景很实用。把两者结合起来还能做出“悬停时颜色变亮贴图替换”的组合效果在性能上开销也很小。4.3 动画与九宫格结合缩放不模糊动画方面九宫格和Transform结合使用也有奇效。按钮弹出动画常用到Scale从0到1的缓动。普通Image在这种缩放下中间的高光纹理和边框的锐利度会迅速劣化九宫格模式下因为四角保持不变整体缩小时和放大时呈现的边框粗细几乎恒定视觉效果更加稳定。不过要注意Render Transform Scale的缩放中心Pivot需要根据需求调整。比如从左上角展开的菜单面板Pivot设为(0,0)从中心弹出的按钮Pivot设为(0.5,0.5)。九宫格背景配合Pivot设计可以模拟出UI从局部展开的效果。5. 常见问题与排查技巧实录5.1 为什么我的图片拉伸后仍然变形这是频率最高的问题。检查顺序如下第一步确认Draw As不是“Image”必须切换为“Border”。很多新手只改了MarginDraw As保持默认Image模式结果自然无效。第二步检查Margin值是否合理。如果原图四角圆角半径是60像素但你只填了20那么圆角向内多出的40像素区域会被当作边部元素拉伸圆角看起来就会变形。反过来如果Margin填得过大比如100角部会直接吃掉中心区域显示效果也会出错。第三步确认贴图的导入设置。在纹理编辑器中检查MipGen。如果开启了Mipmap且尺寸不是2的幂缩放时可能会出现边缘发虚的问题。UI贴图建议关闭Mipmap或者使用“NoMipmaps”选项。第四步查看贴图的压缩设置。对于UI贴图在移动端建议使用“TC_EditorIcon”或“UserInterface2D(RGBA)”压缩格式。不要使用ASTC或ETC2等有损格式处理高精度UI贴图容易产生色块。5.2 九宫格中心区域重复而不是拉伸如果你发现中心区域是重复平铺而不是拉伸多半是因为贴图的纹理寻址模式被设置成Repeat。在UE4的Texture Editor中把Address X/Y改为Clamp即可。Border模式下默认应该是Clamp但旧项目或者从其他引擎导入的资源可能保留了Repeat设置需要手动修正。5.3 九宫格边界出现黑边/亮边出现这个问题的原因通常是贴图边缘的半透明像素没有与透明色很好地过渡。美术导出时如果使用了普通的透明算法边缘像素可能残留了原背景色的RGB值透明度虽然变为0但颜色信息却保留了下来在引擎合成时边缘会出现灰边。解决办法有三种让美术在PS里使用“透明化”操作时保留边缘颜色为最近的内部颜色而不是纯黑或纯白。这在行业内叫“去黑边/去白边”处理。在纹理导入设置中勾选“PremultiplyAlpha”预乘Alpha。预乘可以让半透明边缘的RGB乘以Alpha值黑边或白边被弱化效果明显改善。最稳妥的方案在材质里对UI贴图的边缘做一步处理采样后判断Alpha小于某个阈值时直接clamp掉。但这种方法会损失边缘的平滑度不建议日常使用。5.4 动态修改Margin后没有效果在蓝图里调用Set Brush Margin之后画面没变。这种情况除了检查Draw As是否为Border之外还要确认是不是调用的对象错误。举个例子如果你在某个容器内动态创建了多个Image通过GetAllChildrenOfClass拿到的索引很容易对不上修改了错误的Image。这时候可以在调试模式下断点查看目标Image的Brush属性是否已经被修改。如果数据已经修改但显示没变大概率是UI的渲染缓存没有刷新可以尝试调用一个InvalidatePaintAndLayout节点强制刷新。5.5 不同分辨率下九宫格显示不一致九宫格是按照像素数量切分的所以在不同DPI/分辨率下同样的Margin在屏幕上的物理大小会不同。如果你的项目需要适配PC和手机建议将Margin的值与设计分辨率绑定在初始化时通过一个比例系数缩放Margin。比较稳妥的做法是在设计器中以基准分辨率例如1920x1080设定好Margin值然后根据当前的DPI Scale或者视图比例动态计算并乘以一个缩放因子并在分辨率切换时更新设置。UMG本身有DPI Scaling机制但这些机制只作用于整个控件的缩放不会改变Margin像素值所以特殊场景还是要手动处理。6. 项目实战经验分享最后分享一些我在实际项目中积累的经验供大家参考。九宫格在UE4里不只是一个UI控件的属性它体现的是一套“资源复用”的思维方式。在做界面框架时尽量把背景类贴图全部制作成九宫格资源这样后续新增界面、调整尺寸几乎不需要美术再出图。性能上也更加友好因为同一张贴图可以被大量控件引用显存占用非常低。具体到工作流我习惯在项目里维护一个“UI基础素材库”贴图文件夹里面每张图都有明确的命名规范和对应的九宫格参数文档。用Excel或者Notion维护一张表记录图片文件名、尺寸、Margin四个值、适用场景按钮底图、弹窗背景、列表项背景、输入框背景。UI制作人员直接查表填参数效率提升很大也减少了沟通成本。新手经常走进的一个误区是觉得九宫格只能拉伸成矩形做不出来扇形、椭圆等形状。其实通过调整Margin值可以实现特殊的不规则扩展。例如把Left设为0、Top设为0、Right设为很大值、Bottom设为很大值就能让图片主要从右上角区域展开呈现类似聊天气泡的尾巴朝向变化。配合动态设置Margin还能实现气泡尾巴位置切换。还有一个小技巧在编辑控件蓝图时可以直接选中Image按住CtrlAlt拖动边角预览不同尺寸下的九宫格效果而不需要运行游戏。这个操作很多人不知道但实测非常方便。如果在项目里遇到“图片拉伸模糊”“资源尺寸过多”“界面适配困难”这类问题优先检查是否已经用上了九宫格。至少在我经手的项目里九宫格是性价比极高、回报率极明显的UI技术之一值得花半小时彻底掌握。
返回列表