Unity 2D描边实现介绍

来源:互联网 发布:如何带端口ping 编辑:程序博客网 时间:2024/05/21 16:59

http://www.gad.qq.com/article/detail/26604


  描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个对象,会给对象增加一个描边效果。本篇文章要和大家讲的是Unity 2D的游戏项目中描边的实现方法,下面是具体的实现过程。
  
需求介绍:
  我们的项目是一款2D骨骼动画角色的战棋类回合制游戏,场景如下:


  每回合开始,回合方在战场上的角色,分别有可移动、可攻击或者可移动并且可攻击3种状态,为了让玩家一目了然场上角色的状态,策划想过加icon标记,但是角色buff图标已经足够多了,于是想到给角色身上添加描边特效,这个方式是最直观的方式,又不影响角色buff及属性的显示。
  最终希望得到的效果如下(绿色:可攻击且可移动, 红色:只可攻击, 蓝色:只可移动):


实现过程:
  描边特效的实现,有很多方式,先说说之前尝试的几种方案:

一、像素着色器描边:
  首先最直观的想法,就是使用fragment shader找出2D角色贴图透明像素和非透明像素的边界,然后通过边界周边Alpha值Blur的方式,给边界上描边色,效果如下:


  对于上面贴图的描边效果,是符合我们最初预期的。但是事件并没有这么简单,因为我们游戏的是2D骨骼动画角色,它是有多个面片叠加起来的一个复杂的角色,使用上述的方式进行描边处理,得到的效果就不尽人意了,如下是我们的2D骨骼角色的截图:


  使用的贴图如下所示:


  通过上述方式描边的效果,完全不符合预期:


  上述方法行不通,主要有两个方面原因:
  一个是:2D骨骼动画角色是由许多面片重叠而成,导致每个面片的描边叠加到一起,而不是在角色整体上进行描边。
  另一个原因是:上述方法是以贴图透明和不透明像素边界来找出描边边界的,2D骨骼动画角色的贴图不透明像素周边的透明像素“厚度”很不均匀,在描边效果要达到一定粗细程度的情况下,这种贴图显然很不理想。

二、后处理+像素着色器描边:
  于是,很自然的想到,使用Postprocessing 的方式来处理屏幕最终渲染出来的仅包含有需要描边的角色的图片,然后进行上述的fragment描边处理。
  首先,在场景中添加一个专用的描边相机,Depth设为比默认相机高一级,视口大小、位置全部和默认相机一致。另外给场景物体添加一个"Outline1"layer,设置到专用相机的cullingmask,需要描边的角色的layer都设置为"Outline1"。


  这个时候专用相机只渲染描边物体,然后给相机添加Monobehavior脚本,在OnRenderImage里对相机渲染的图像进行像素着色器的描边处理,得到如下效果:

 

  描边效果的确是预期的效果,但是还是有两个问题:
  一个是:由于我们游戏UI是使用Screen space - camera的方式,它和游戏中对象都是在默认相机渲染的,专用相机的depth比默认相机高一级,所以所有渲染内容都会在UI层次之上,这显然也不是我们想要的。
  另一个是:角色的不同行动状态需要用不同的描边颜色来区分,上述方式只支持一种描边颜色。

 
三、RenderTarget + 像素着色器描边:
  现在我们着重来解决上述两个问题:
第一个遮挡UI的问题:
  描边效果需要在默认相机中进行z轴排序,让其渲染在UI之后,所以,我们需要让描边效果作为一个默认相机渲染的常规游戏对象放到游戏中。于是,我想到的是给它创建一个和屏幕尺寸同大小的Mesh,再将描边渲染的图片放到Mesh上,所以,做法是给专用相机分配一个屏幕尺寸同大小的RenderTarget,然后将RenderTarget渲染到创建的Mesh上。如下图所示,该Mesh在骨骼动画和相机之间创建。

 

第二个颜色区分的问题:
  查询Unity Camera的API有两个回调接口可以用:
  OnPreRender 在相机渲染场景之前被调用。
  OnPostRender 在相机完成场景渲染之后被调用。
  我们给专用相机添加这两个回调,
在OnPreRender里:
  给所有需要描边的物体更换Material,该Material负责绘制该物体的状态纯颜色到RenderTarget上,并保存原有Material。
在OnPostRender里:
  将原有Material又置换回来供默认相机正常渲染。得到的RenderTarget如下,


  这个时候,再用像素着色器对应用了RenderTarget的Mesh进行描边,得到如下效果


  以上就是我们项目解决描边特效过程中遇到的问题以及相关方案,我们最终采用了第三种方案,最终也较为完美的解决了策划的需求。希望这篇文章能够帮助到有类似需求的项目组,当然,如果有更好方案的同学欢迎多交流。

原创粉丝点击