[Unity] Unity Sprites:SpriteRenderer 与 CanvasRenderer(UI 图像)

RuntimeMapMaker3D-Pro在这里插入图片描述


英文原文:https://thegamedev.guru/unity-ui/sprite-vs-image/

在为我们的一个客户做项目时,我被问及Unity中的精灵(SpriteRenderer)和UI图像(CanvasRenderer)的区别。我没有找到太多的相关信息,所以我决定在我的公司里准备一个演示文稿,以帮助解释清楚它。在这篇文章中,你会发现我为它准备的原始幻灯片的一个更详细的版本。这篇博客文章将以Unity 5.3.4f1为基础。

  Sprites基本上是半透明的纹理,在其纹理导入设置中被导入为sprite。它们不像纹理那样直接应用于网格,而是应用于矩形/多边形(最后,它们也是网格,所以没有这么大的区别)。Sprites是将在你的2D/3D场景或界面中渲染的图像。

1. 使用方法

  在Unity中使用 sprite 是很直接的。只要把所需的图片(最好是PNG格式)放到assets文件夹中,然后点击它,进入检查器设置。把它标记为精灵(2D和UI),如下面的截图所示。

在这里插入图片描述
  现在是时候让你决定是把它作为一个sprite还是作为一个UI Image。但如果你正在读这篇文章,你可能不确定你想要哪种方法。我们将在下一节中描述两者的区别;现在我们只需快速概述一下如何创建这两种方法。

  如果你想使用SpriteRenderer,只需将sprite从项目视图中放入层次结构或场景视图中。新的GameObject的检查器将看起来像。

在这里插入图片描述
如果你想创建一个UI Image,只需在层次结构中点击右键并创建新的用户界面->图像。这个组件需要一个画布,所以如果你还没有画布,它就会被创建。最后,它将看起来像。

在这里插入图片描述

2. 比较。SpriteRenderer vs CanvasRenderer

  当涉及到层次结构时,你可以在你的场景中的任何地方放置sprite。另一方面,UI图像必须在一个画布内(一个拥有画布组件的游戏对象)。你可以像所有其他对象一样通过Tranform来定位sprite,但Image将使用RectTransform来代替,以便帮助在你的界面系统中定位图像。sprite在透明的几何队列中被渲染(除非你使用默认以外的其他材质)。UI图像也在透明几何队列中渲染(Render.TransparentGeometry),除非你使用叠加渲染模式,在这种情况下它将通过Canvas渲染。

  RenderOverlay。正如你可能已经猜到的,在移动端绘制它们的成本相对较高。我们将在后面解释原因。

  sprite和Image的一个关键区别是,sprite支持自动创建网格,而UI图像总是由矩形组成。创建网格的原因将在下一节解释;我们将看到它的重要性,因为它对性能有重要影响。

  最后,两者都可以与sprite atlases一起使用,以减少绘制调用。这很好。

  这可能有助于通过具体的例子看到其中的差异。

在这里插入图片描述
  看看例1中两种方法的区别。UI Image创建了一个紧密的矩形,将sprite包裹起来,而SpriteRenderer则创建了一个更适合我们正在渲染的sprite的网格。让我们来看看另一个例子。

在这里插入图片描述
在这里插入图片描述
  同样,同样的情况也发生在例子2中。但是现在的网格看起来要复杂得多,这是为什么呢?Unity试图在不引入太多多边形的情况下尽可能地适合精灵,所以这就是我们得到的结果。人们可以争论一下,这样的权衡是否有益。如果我们导入一个带有岛屿的PNG图像,例如一个包含有透明区域分隔的不同图形的图像,现在会发生什么?

  第三个例子的结果非常有趣。SpriteRenderer创建了两个子网格,每个岛一个;然而,UI Image扩展了矩形,所以它覆盖了整个图像。无论如何,这很重要吗?

3. 性能

  你猜对了,这与性能密切相关。如果你要渲染很多这样的东西(比如地形中的草,或者粒子),它确实会产生巨大的差别。因此,让我们来分析一下其中的原因。

  每当你渲染一个纹理时,你需要向GPU驱动发送一个命令。你要设置一些信息,比如顶点、索引、uv坐标、纹理数据和着色器参数,然后进行著名的绘制调用。之后,在最终的图像显示在你的屏幕上之前,在GPU中会发生一些讨厌的事情。一个(真正)简化的渲染管线包括以下内容:

  1. CPU向GPU发送一个绘图命令。
  2. GPU获得它所需要的所有绘图信息(比如将纹理复制到它的VRAM,如果它有的话)。
  3. 发送的几何图形通过顶点着色器和光栅化器被转化为像素。
  4. 每个像素都通过 fragment 着色器进行转换,并一次或多次写入帧缓冲区。
  5. 当帧完成后,图像会显示在你的屏幕上。

  那么回到主题,SpriteRenderers和UI图像之间的区别是什么?看起来,sprite的成本更高,因为它的几何形状更复杂。但如果我告诉你,顶点操作通常比片段操作更便宜呢?这对于Mobile和半透明的物体来说尤其如此。但为什么呢?

  在许多引擎中,包括Unity,半透明的材质是从后往前渲染的。这意味着,最远的物体(离摄像机)总是先被绘制出来,所以alpha混合操作会如期进行。对于不透明的材质,情况正好相反,所以我们可以剔除不可见的物体。

  像素着色器将为你正在渲染的sprite的每一个(可见)像素执行,所以如果你有一个巨大的精灵(相对于屏幕尺寸),那么你将在许多像素上执行片段着色器。透明物体的问题是,如果它们位于你的相机范围内,你就不能有效地剔除它们,所以基本上你要渲染所有的半透明物体,即使它们中的许多在最后都不可见。所以你会发现自己多次渲染相同的像素,并在帧缓冲区中一直覆盖它们。这个问题通常被称为overdraw。是的,这是一个问题,因为它浪费了内存带宽,而且你会很快达到你的GPU的像素填充率限制,如果你的目标是移动设备,这是你不能允许的。这就是需要理解的关键点。

  现在,如果你真的理解了它,你也会明白为什么SpriteRenderer和CanvasRenderer如此不同。前者创建的网格消除了不需要的透明像素(因此避免了执行昂贵的片段着色器并减少了超绘),而UI Image创建的简单网格可能会引起大量的超绘。在拥有复杂的几何图形或忍受更多的片段操作之间,你总是要取得一个平衡。

  你应该总是考虑使用sprite atlases,因为sprite通常数量很多,但尺寸很小。这就导致了有那么多的绘制调用作为精灵,而这并不是好事。另外,如果你有较大的图像,图像压缩效果会更好。

在这里插入图片描述
  你可以通过Atlas Packer轻松创建 sprite 图集。不过,有时自动创建的网格并不理想,而且你也无法控制它,所以你可以考虑使用更高级的软件,如ShoeBox或TexturePacker。

在这里插入图片描述

4. 总结

下次你在使用sprite时,请考虑以下问题。

  1. 如果你只有几个sprite,使用你喜欢的任何东西。如果你有成百上千的精灵,请重读本帖。
  2. 使用 profiler 和 frame debugger 来了解正在发生的事情。
  3. 避免使用透明度。如果你的预算允许,可以尝试用不透明的替代品来取代精灵。
  4. 避免在屏幕上渲染大的sprite,因为会发生更多的overdraw。你可以在场景视图中通过选择 overdraw 作为渲染模式来轻松检查 overdraw 问题。这对粒子系统至关重要。
  5. 比起大量的像素,我们更喜欢拥有一个更复杂的几何体,尤其是在移动端。在场景视图中检查结果,把它渲染成阴影线框。
  6. 如果你需要界面定位助手(如内容适配器、垂直分组等),请选择UI图像。
  7. 要知道你是否遇到了像素填充率的限制,请检查通过降低渲染区域的分辨率,性能是否得到了大幅提高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值