7

UGUI研究院之在UI上使用RenderTexture显示模型+AlphaBlend特效(二十五)

 3 years ago
source link: https://www.xuanyusong.com/archives/4318
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

UGUI研究院之在UI上使用RenderTexture显示模型+AlphaBlend特效(二十五)

雨松MOMO 【UGUI研究院】 围观4206019 条评论 编辑日期:2017-03-31 字体:

在UI上显示模型无非就是2种。

1.在两个UI摄像机中夹一层3d摄像机,利用摄像机的Viewport Rect属性对模型进行裁切。

2.使用RenderTexture渲染在RawImage后显示在UI上。

我上一个项目就是采取第一种方法,用起来很不舒服。因为有很多效果都做不了,比如就是UI上盖模型,在盖UI,再盖模型这种,还有就是在滑动列表中显示模型,滑动裁切的话都很麻烦。

今天我想说的就是第二种,使用RenderTexture的方式来渲染模型。

先说缺点:

1.为了保证显示上的效果RenderTexture的文件区域必须大于RawImage的区域,我们目前用的是乘2倍。比如RawImage的区域是512X512,那么就得创建一个1024X1024大小的RenderTexture才能保证渲染效果。

2.如果人物身上有一些特殊的效果,比如outline描边这样的,放在RenderTexture上就是达不到效果。

3.如果模型身上带有AlphaBlend这样的特效,因为AlphaBlend要和背景做混合,而RenderTexture不像Camera那样有背景,显示上就会有问题。(下面我会说我目前是怎么解决的)

优点的话,就很爽了。完全和UI一样,层级顺序,列表中显示模型、裁切、等等都很方便了。

RenderTexture显示AlphaBlend特效的方法

因为AlphaBlend特效需要和背景做混合,所以我们可以给它后面垫一个底图。这样就能解决在RenderTexture上显示带AlphaBlend的特效的模型。

创建一个Sprite 可以直接把UI的Sprite放上去。如果模型带特效就用Sprite2d,如果模型不带特效,完全可以用之前UI的制作方式,很方便灵活的切换它。

UGUI研究院之在UI上使用RenderTexture显示模型+AlphaBlend特效(二十五) - 雨松MOMO程序研究院 - 1

如下图所示,Game视图中显示的效果,这个翅膀的火焰特效就是alphablend

UGUI研究院之在UI上使用RenderTexture显示模型+AlphaBlend特效(二十五) - 雨松MOMO程序研究院 - 2

如下图所示,因为底图不止一张,大家看到下面还有好几张花纹了吗?都可以用Sprite2d叠在下面。

渲染RenderTexture的摄像机,这里已经能看出来渲染的是正确的,下面被水印挡住了 图片尺寸是1401*540 ARGB32 4.3M。为什么尺寸这么大呢?上面我也提过,因为RenderTexture尺寸和RawImage一样的话,效果会比较差,所以这里乘了2倍。

这样问题来了,摄像机的大小或者fov变了,那岂不是每次都要手动去把sprite的size对齐,手动设置localScale。这样就太麻烦了。

下面我再给大家分享一个脚本,正交或者非正交摄像机都支持的。自动根据摄像机的区域来自动自适应计算sprite的size 。(这个脚本挂在Sprite上即可)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpriteFull : MonoBehaviour {
//设置SpriteRender和摄像机的距离
public float distance = 1.0f;
private SpriteRenderer spriteRenderer = null;
void Start()
spriteRenderer = GetComponent<SpriteRenderer> ();
spriteRenderer.material.renderQueue =2980; //这段代码非常重要!!!大家务必要加上,不然透明的渲染层级会出错
void Update()
Camera camera = Camera.main;
camera.transform.rotation = Quaternion.Euler (Vector3.zero);
float width = spriteRenderer.sprite.bounds.size.x;
float height = spriteRenderer.sprite.bounds.size.y;
float worldScreenHeight,worldScreenWidth;
//这里分别处理正交和非正交摄像机
if (camera.orthographic) {
worldScreenHeight = Camera.main.orthographicSize * 2.0f;
worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;
} else {
worldScreenHeight = 2.0f * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
worldScreenWidth = worldScreenHeight * camera.aspect;
transform.localPosition = new Vector3 (camera.transform.position.x, camera.transform.position.y, distance);
transform.localScale = new Vector3 (worldScreenWidth / width, worldScreenHeight / height, 0f);

上面有段代码非常重要,切记一定要设置sprite的renderQueue ,因为ui是3000这里和UI不一样就行,不然透明会显示错误。

最后,垫在模型下面可能一张图是不够的,可能还有一些花纹,可能还有花纹需要镜像等,这样的图片就得需要手动设置一下缩放和位置了。

OK 大家如果有疑问欢迎再下面给我留言,继续干活了~

作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK