深入理解NGUI(Unity)显示特效的问题

原文地址:深入理解NGUI(Unity)显示特效的问题

粒子特效显示差异引出问题

游戏开发时常会需要在UI里显示一个特效,我们将特效在UI里显示出来后,发现效果不符合预期。该特效在普通3D场景下,效果如下:

http://km.oa.com/files/post_photo/370/210370/a057548d43fb06251e01cdda42e39417.jpg

图1

但在UI里效果偏差比较大:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image002.jpg

图2

该特效是由多个粒子器组合而成。对于显示差异,我们对比了其中一个粒子器在渲染时的Mesh细节:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image003.jpg

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image004.jpg

图3

如上图左边是正确效果,右边是UI中错误效果。原本怀疑粒子系统的运动坐标系是否参照World而非Local导致观察运动方向不同,但查看各粒子属性和坐标Gizmo排除此可能性。

 

经过一天的努力,找到上述问题的本质原因。但让我们先回顾一些知识。

 

粒子渲染

美术在制作粒子时通常偏好使用Additive Shader这中渲染方式适用于大部分明亮的例如火焰型、光感型特效。

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image005.jpg

其主要计算法则如下:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image006.gif

当Texture使用http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image007.gif通道时:

SrcBlend = SRC_ALPHA;

DestBlend = ONE;

BlendOp = ADD;

 

当Texture不使用http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image007.gif通道(通常已经预先乘到RGB分量中):

SrcBlend = ONE;

DestBlend = ONE;

BlendOp = ADD;

 不难看出,该方式的最终效果受http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image008.gif影响。因此在光亮度(luminance)不同的背景下会呈现不同的显示效果。显然,图1、2两个特效的http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image008.gif相近,故排除此种可能。

NGUI的UI坐标系详解

UI的工作一般是从这样一个环境下开始:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image009.jpg

图4

UIRoot的Hierarchy和Inspector如下图:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image010.jpg

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image011.jpg

图5

图4中的orthographic摄像机的属性是:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image012.jpg

不难得出该摄像机的可视区域是2 X 3 X 29(World坐标系)的立方体,大小不会随着Camera GameObject的Hierarchy层级关系改变而变化。此摄像机的宽是高的1.5倍(宽高比3:2)。

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image013.jpg

图4中的红色框即NGUI里Panel的Gizmo。可认为是Camera的投影平面。显然该Gizmo的大小在World下为2 X 3。那如何表示该投影坐标系下的960 X 640范围呢?NGUI巧妙利用空间坐标系转换来实现这一点。

在图5中,UIRoot是一切UI Hierarchy的根。如果我们通过B中设置投影平面的Height,可以发现相应的UIRoot的Transform的Scale在对应改变,同时红色Gizmo的大小不发生任何改变。阅读UIRoot的代码可以看到,UIRoot每帧都会主动调整Transform的Scale匹配上投影平面的大小。

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image014.jpg

那为什么需要特别对应此种关联呢?根据分析,有如下猜想:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image015.jpg

图6

UIRoot既然是根节点,那么该根节点的Scale改变,也就映射出UI Camera投影坐标系和世界坐标系的比例关系。即:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image016.gif

其中http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image017.gif

那么在所有UI下的Widget进行Local Position Y(X)方向移动一个单位时,也就会对应到UI Camera投影坐标系中的一个单位,而在World下只移动了http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image018.gif(http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image019.gif)单位

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image020.jpg

 

根据Viewport调整UI Camera投影坐标系

最后再根据Viewport坐标系调整UI Camera投影坐标系范围。

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image021.jpg

设Back Buffer的分辨率为 H * W

NGUI提供了三种方式

Scaling Style

 Height取值

Width取值

Fixed Size

Height=http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image022.jpg

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image023.gif 

Pixel Perfect

Height = H ,  Clamp To

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image024.jpg

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image023.gif 

Fixed Size On Mobiles

在Unity Build里切换成移动平台后同Fixed Size否则同Pixel Perfect

在Unity Build里切换成移动平台后同Fixed Size否则同Pixel Perfect

参考代码如下:

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image025.jpg

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image026.jpg

 

这样调整的意义在于保证Widget在Y方向进行后续光栅化时不会走样失真。对于手机开发,通常使用

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image027.jpg

就可以较好匹配这两种主流分辨率。

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image028.jpg

问题解决

读到这里,大家一定不难发现,开头两个特效渲染不正确的问题是坐标系不统一导致的。

http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image029.jpg

上图红框里Box X是粒子初生的范围,为1,这个坐标系是在Local下的。因此也就是UI Camera的投影坐标系的单位1,变换到World将是非常小的一个距离http://avocado.oa.com/fconv/files/201408/87239dfbcd7cbff7e102212826c55f46.files/image018.gif。该特效的制作是在World场景下,显然转换到UI投影坐标系会产生较大偏差,这就是上述问题的本质原因。

 

总结

1.  美术在制作特效时,须要在正确应用的坐标系下创作(区分是UI Projection还是World)。

2.  美术在UI上使用粒子特效时,一定要注意应用背景的颜色。

此文通过解决这个问题来梳理一下UI的基础知识,帮助程序更好理解NGUI。如有不正确的地方,欢迎指出以便共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值