首页 > Unity3D频道 > 【UGUI研究院】 > UGUI研究院之Mask裁切UI粒子特效或者3D模型(十七)
2015
06-02

UGUI研究院之Mask裁切UI粒子特效或者3D模型(十七)

刚好前几天有人问我这个问题,再加上新项目也可能用,所以这两天就研究了一下。其实如果粒子特效 和3D模型 都用RenderTexture来做的话就不会有裁切的问题,但是粒子特效用RenderTexture来做会有显示的问题,所以还是得用摄像机。废话不多说了,进入正题。

原理就是把Mask的裁切区域传给粒子特效Shader,当超出这个区域那么直接让它完全透明即可。粒子特效的源生shader大家可以去unity官网下载,我在这里把需要修改的地方标注给大家。

//add 注释中的内容就是我做修改的地方。

然后是自己写了个类继承Mask。把Mask的区域传给shader。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class MyMask :Mask
{
protected override void Start ()
{
base.Start ();

int width = Screen.width;
int height = Screen.height;
int designWidth = 960;//开发时分辨率宽
int designHeight = 640;//开发时分辨率高
float s1 = (float)designWidth / (float)designHeight;
float s2 = (float)width / (float)height;

//目标分辨率小于 960X640的 需要计算缩放比例
float contentScale =1f;
if(s1 > s2) {
contentScale = s1/s2;
}
Canvas canvas = GameObject.Find(“Canvas”).GetComponent<Canvas>();
Vector2 pos;
if(RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, transform.position, canvas.camera, out pos)){
ParticleSystem [] particlesSystems = transform.GetComponentsInChildren<ParticleSystem>();
RectTransform rectTransform = transform as RectTransform;
float minX,minY,maxX,maxY;
minX = rectTransform.rect.x + pos.x;
minY = rectTransform.rect.y+ pos.y;
maxX = minX + rectTransform.rect.width ;
maxY = minY + rectTransform.rect.height;

//这里 100 是因为ugui默认的缩放比例是100 你也可以去改这个值,但是我觉得最好别改。
foreach(ParticleSystem particleSystem in particlesSystems)
{
particleSystem.renderer.sharedMaterial.SetFloat(“_MinX”,minX/100/contentScale);
particleSystem.renderer.sharedMaterial.SetFloat(“_MinY”,minY/100/contentScale);
particleSystem.renderer.sharedMaterial.SetFloat(“_MaxX”,maxX/100/contentScale);
particleSystem.renderer.sharedMaterial.SetFloat(“_MaxY”,maxY/100/contentScale);
}
}
}
}
上面这段代码写的不太好,有一个更好的办法来取Mask的裁切区域。

通过GetWorlCornets来确定裁切的区域

然后在把裁切的区域传到shader中。

为了做到不影响美术,所以美术开发特效的时候还是用以前的shader。程序在运行中对它进行更换,这样可以无缝进行切换。

如果运行时裁切区域发生变化, 可以重写OnRectTransformDimensionsChange()方法来重新给材质赋新的裁切区域

OK,如下图所示,把粒子特效直接挂在Mask下面, 就可以进行裁切了。。

UGUI研究院之Mask裁切UI粒子特效或者3D模型(十七) - 雨松MOMO程序研究院 - 1

在说一下3D模型, 理论上用上述的shader改一改就可以。 但是我还是建议3D模型用RenderTexture。比较好控制深度。

最后是工程的下载地址:http://pan.baidu.com/s/1pJFV5ph

希望大家可以多多测试一下,看看有没有问题。 或者你有更好的方法,欢迎在下面给我留言。谢谢啦~

后记:

1.感谢楼下 @姜华 提出了一个新方案

这个方法非常巧妙, 我也尝试的使用了一下。但是遇到了个问题,当我有两个裁切区域,发生重合的时候就会出问题。如果大家没有这样重合的需求。也可以参考他的方法。

2.asset store上有一个Unity Particle 2D 的插件,大家也可以试试。

 

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

UGUI研究院之Mask裁切UI粒子特效或者3D模型(十七)》有 51 条评论

  1. 冬晓 说:

    Unity2017以后 ParticleSystem的Renderer中有了Masking属性(None、Visible Inside Mask、Visible Outside Mask),和SpriteMask组件结合和作出粒子遮罩的效果。参考链接:https://blog.csdn.net/Fenglele_Fans/article/details/81101511

  2. 张思懿 说:

    雨松大大,NGUI用这个shader发现,粒子特效是可以的,模型却不行,这是为啥啊
    Vector3 t = transform.TransformPoint(new Vector3(-cr.z + cr.x, 0)) – _uiroot.transform.position;
    ren.sharedMaterial.SetFloat(“_MinX”, t.x);

    Vector3 t1 = transform.TransformPoint(new Vector3(cr.z + cr.x, 0)) – _uiroot.transform.position;
    ren.sharedMaterial.SetFloat(“_MaxX”, t1.x);

    Vector3 t2 = transform.TransformPoint(new Vector3(0,-cr.w + cr.y)) – _uiroot.transform.position;
    ren.sharedMaterial.SetFloat(“_MinY”, t2.y);

    Vector3 t3= transform.TransformPoint(new Vector3(0,cr.w + cr.y)) – _uiroot.transform.position;
    ren.sharedMaterial.SetFloat(“_MaxY”, t3.y);

    这是计算位置的代码

留下一个回复

你的email不会被公开。