之前写过一篇单个 UIPanel 对粒子的裁剪,地址是:https://www.cnblogs.com/jietian331/p/5075487.html

但项目中有时会遇到多个UIPanel,如下面问题,UISprite 被剪裁了,但粒子未被剪裁:

转载请注明出处:https://www.cnblogs.com/jietian331/p/10938837.html

这时解决问题的思路是,找出所有的有剪裁功能的 UIPanel,并求出它们剪裁区域的交集然后传到shader中,效果如下:

代码如下:

 using System.Collections.Generic;
using UnityEngine; namespace Modules.UI
{
// 对子节点下所有的粒子和模型进行剪裁,且支持多个 UIPanel
public class EffectClip : MonoBehaviour
{
List<Material> m_materials;
List<UIPanel> m_uiPanels;
UIRoot m_uiRoot; #region Properties UIRoot ObjUIRoot
{
get
{
if (!m_uiRoot)
m_uiRoot = GetComponentInParent<UIRoot>();
return m_uiRoot;
}
} // 找到所有粒子,模型的material
List<Material> Materials
{
get
{
if (m_materials == null)
{
m_materials = new List<Material>(); // particle system 的剪裁
var particleSystems = GetComponentsInChildren<ParticleSystem>();
for (int i = , j = particleSystems.Length; i < j; i++)
{
var ps = particleSystems[i];
var mat = ps.GetComponent<Renderer>().material;
string shaderName = mat.shader.name + ""; // 所用shader,重写一份带剪裁功能的
Shader shader = Shader.Find(shaderName);
if (shader)
{
m_materials.Add(mat);
mat.shader = shader;
}
else
{
Debug.LogError("Shader not found, name: " + shaderName);
}
} // mesh 的剪裁
var renders = GetComponentsInChildren<MeshRenderer>();
for (int i = , j = renders.Length; i < j; i++)
{
var ps = renders[i];
var mat = ps.material;
string shaderName = mat.shader.name + ""; // 所用shader,重写一份带剪裁功能的
Shader shader = Shader.Find(shaderName);
if (shader)
{
m_materials.Add(mat);
mat.shader = shader;
}
else
{
Debug.LogError("Shader not found, name: " + shaderName);
}
}
}
return m_materials;
}
} List<UIPanel> Panels
{
get
{
if (m_uiPanels == null)
{
// 获取所有开启剪裁的 UIPanel
m_uiPanels = new List<UIPanel>();
UIPanel[] panels = GetComponentsInParent<UIPanel>();
for (int i = ; i < panels.Length; i++)
{
UIPanel p = panels[i];
if (p && p.clipping == UIDrawCall.Clipping.SoftClip)
{
m_uiPanels.Add(p);
}
}
}
return m_uiPanels;
}
} #endregion void Update()
{
var mats = Materials;
if (mats != null && mats.Count > )
{
for (int i = ; i < m_materials.Count; i++)
{
Vector4 area = CalcClipArea();
m_materials[i].SetVector("_Area", area);
}
}
} // 整合所有 UIPanel 的剪裁区域
Vector4 CalcClipArea()
{
var panels = Panels;
float x = float.MinValue, y = float.MinValue, z = float.MaxValue, w = float.MaxValue; // 求所有 UIPanel 剪裁区域的交集
for (int i = ; i < panels.Count; i++)
{
UIPanel p = panels[i];
Vector4 area = CalcClipArea(p); // 求交集啊
if (area.x > x)
x = area.x;
if (area.y > y)
y = area.y;
if (area.z < z)
z = area.z;
if (area.w < w)
w = area.w;
} return new Vector4(x, y, z, w);
} // 计算单个 UIPanel 的剪裁区域
Vector4 CalcClipArea(UIPanel p)
{
float h = ;
float temp = h / ObjUIRoot.activeHeight;
Vector3 offsetV3 = new Vector3()
{
x = p.clipOffset.x * temp,
y = p.clipOffset.y * temp,
};
Vector3 worldPos = p.transform.position + offsetV3;
Vector4 clipRegion = p.finalClipRegion;
Vector4 nguiArea = new Vector4()
{
x = -clipRegion.z / ,
y = -clipRegion.w / ,
z = clipRegion.z / ,
w = clipRegion.w /
}; return new Vector4()
{
x = worldPos.x + nguiArea.x * temp,
y = worldPos.y + nguiArea.y * temp,
z = worldPos.x + nguiArea.z * temp,
w = worldPos.y + nguiArea.w * temp
};
} }
}

EffectClip

Unity NGUI 多个UIPanel对粒子的剪裁的更多相关文章

  1. Unity NGUI 粒子的排序

    Unity NGUI系统中是没有对粒子进行排序的,如: 怎么解决这个问题呢? 思路是把粒子的渲染层级,相对于UI组件的层级进行一个偏移. 解决后的效果如下: 代码如下: using System.Co ...

  2. unity NGUI点击消息不传入到场景中去

    unity NGUI点击消息不传入到场景中去 1.今天遇到的问题是点击NGUI的按钮,场景中也相应了这个消息 解决的办法是在场景中需要互动的时候,也就是在update中进行判断 是否是点击了NGUI按 ...

  3. Unity NGUI 网络斗地主 -发牌 脚本交互

    Unity NGUI 网络斗地主 -发牌 脚本交互 @By 灰太龙 Unity4.2.1f4 NGUI 3.0.4 本篇说的问题是脚本与控件的交互! 现在对界面进行了改进,先看副图! 1.制作发牌效果 ...

  4. Unity NGUI 网络斗地主 -制作图集 Atlas

    Unity NGUI 网络斗地主 -制作图集 Atlas by @杨海龙 开发环境   Win7+Unity4.2.1f4+NGUI 3.0.4版本 这一节告诉大家如何制作(图集)Atlas! 1.首 ...

  5. Unity NGUI 网络斗地主 -界面制作

    Unity NGUI 网络斗地主 -界面制作 源文件在群(63438968群共享!) @灰太龙 这一节说一下NGUI的界面摆放,并且教会大家使用NGUI的自适应功能! 在这里感谢@Gamer,是他给我 ...

  6. Unity NGUI 3.0.4版本 制作网络版斗地主

    Unity NGUI 3.0.4版本 @by 灰太龙  开发环境 Win7旗舰版 Unity 4.2.1f4 本文就写个开门篇,告诉大家怎么用NGUI,第一步导入NGUI 3.0.4版本! 1.启动U ...

  7. BMFont中文字体图集制作的方法~(for unity ngui)

    BMFont中文字体图集制作的方法~(for unity ngui) 好吧~似乎这个问题困扰了很多人,游戏开始中文化是个不错的事儿啊,这里我就做下说明,如何制作中文字体图集~ 这里的字库图集的制作更多 ...

  8. Unity NGUI UIPanel下对粒子的剪裁

    使用 unity 做游戏开发时,有时需要在scroll view下使用粒子,但粒子是不会被 UIPanel 所裁剪的,本人提供了脚本 ParticleSystemClipper,用来处理这种情况.思路 ...

  9. Unity NGUI和UGUI与模型、特效的层级关系

    目录 1.介绍两大UI插件NGUI和UGUI 2.unity渲染顺序控制方式 3.NGUI的控制 4.UGUI的控制 5.模型深度的控制 6.粒子特效深度控制 7.NGUI与模型和粒子特效穿插层级管理 ...

随机推荐

  1. 【mac】配置sublime开发C

    1.sublime text3,Tools/Build System/New Build system创建一个新配置文件. {"cmd": ["gcc", &q ...

  2. PAT_A1124#Raffle for Weibo Followers

    Source: PAT A1124 Raffle for Weibo Followers (20 分) Description: John got a full mark on PAT. He was ...

  3. python类的实例方法、静态方法和类方法区别及其应用场景

    https://blog.csdn.net/helloxiaozhe/article/details/79940321 普通实例方法,第一个参数需要是self,它表示一个具体的实例本身. 如果用了st ...

  4. vue组件通信之非父子组件通信

    什么顺序不顺序的.. 先来说说非父子组件通信. 首先,我们先来了解下vue中的 1.$emit  触发当前实例上的事件,附加参数都会传给监听器回调. 2.$on  监听当前实例上的自定义事件.事件可以 ...

  5. 剑指offer——64和为s的数字

    题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 题解 ...

  6. PXE装机

    支持 centOS 6 支持 PXE 装机的网卡必须自带 ROM(非意识性存储器)存储内容包括:DHCP 客户端,TFTP 客户端,PXE 协议客户端,将网卡设置第一启动项. DHCP:自动分配 IP ...

  7. Spring IOC源码分析(一):ApplicationContext体系结构设计之自底向上分析

    spring-context包1. ApplicationContext接口 public interface ApplicationContext extends EnvironmentCapabl ...

  8. 注册页面-使用form模块搭建

    基于Django的form模块,快速的搭建注册页面,每个限制条件,都放在form模块里面,不单独对每一项编写标签,使用模版的 for 循环来渲染. 首先设置form模块 在blogs模块下创建一个bl ...

  9. <python基础>python继承机制

    子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找. 根据父类定义中的顺序,以深度优先的方式逐一查找父类! class D: def show(self) ...

  10. B-彻底删除卸载Ubuntu中的MySQL并重新安装(已验证)

    Ubuntu-16.04,MySQL-5.7,寻找多篇有关如何彻底卸载删除MySQL的博文, 最终验证下面转发博文真实有效,推荐! https://www.jianshu.com/p/c76b31df ...