写在开篇:

越来越烦那些无脑转发自己不做验证的博主论坛楼主,网上好不容易找到一些资料,结果代码搞下来却是错的,有些确实是因为版本问题太老不兼容,但是有些明显是有问题的,转发前自己试试就知道肯定是不能用的。结果。。。哎。。。真是不想说啥了。

这次是在小地图中画线画圈,用到了动态绘制Mesh,小地图需要对这些线进行裁切,所以去网上搜了一篇叫做《Unity NGUI UIPanel下对粒子的剪裁》的文章。当然还是感谢一下原作者提供的思路。我这里对这篇文章中涉及到的代码进行了优化改动,使之可以使用。没错!使之可以使用!!!不然没法用啊啊啊啊!!!还有让我最抓狂的一点,就是某些特定分辨率下裁切范围有问题的bug,我也改掉了!!!

废话不多说了,上代码

CustomUIClipper.cs

usingSystem;usingUnityEngine;[RequireComponent(typeof(UIPanel))]publicclassCustomUIClipper:MonoBehaviour{conststringShaderName="Bleach/ParticlesAdditiveAreaClip";constfloatClipInterval=0.5f;UIPanelm_targetPanel;Shaderm_shader;voidStart(){//findpanelm_targetPanel=GetComponent<UIPanel>();if(m_targetPanel==null)thrownewArgumentNullException("Cann'tfindtherightUIPanel");if(m_targetPanel.clipping!=UIDrawCall.Clipping.SoftClip)thrownewInvalidOperationException("Don'tneedtoclip");m_shader=Shader.Find(ShaderName);//if(!IsInvoking("Clip"))//InvokeRepeating("Clip",0,ClipInterval);Clip();}Vector4CalcClipArea(){varclipRegion=m_targetPanel.finalClipRegion;Vector4nguiArea=newVector4(){x=clipRegion.x-clipRegion.z/2,y=clipRegion.y-clipRegion.w/2,z=clipRegion.x+clipRegion.z/2,w=clipRegion.y+clipRegion.w/2};varuiRoot=m_targetPanel.root;varpos=m_targetPanel.transform.position;floatrate1=(float)Screen.width/(float)Screen.height;floatrate2=(float)uiRoot.manualWidth/(float)uiRoot.manualHeight;floath=2f;floatw=h*rate1;floattempH=h/uiRoot.manualHeight;floattempW=w/uiRoot.manualWidth;floattempRate=Mathf.Max(tempW,tempH);if(rate1<rate2){tempRate=Mathf.Min(tempW,tempH);}Vector4result=newVector4(){x=pos.x+nguiArea.x*tempRate,y=pos.y+nguiArea.y*tempRate,z=pos.x+nguiArea.z*tempRate,w=pos.y+nguiArea.w*tempRate};returnresult;}voidClip(){Vector4clipArea=CalcClipArea();Renderer[]renderers=GetComponentsInChildren<Renderer>();for(inti=0;i<renderers.Length;++i){varmat=renderers[i].material;if(mat.shader.name!=ShaderName)mat.shader=m_shader;mat.SetVector("_Area",clipArea);}}voidOnDestroy(){//CancelInvoke("Clip");}}

将这个文件挂载到带有裁切功能的UIPanel上

这个Panel下的粒子或者Mesh使用的shader代码如下:

Shader"Bleach/ParticlesAdditiveAreaClip"{Properties{_TintColor("TintColor",Color)=(0.5,0.5,0.5,0.5)_MainTex("ParticleTexture",2D)="white"{}_Area("Area",Vector)=(0,0,1,1)}Category{Tags{"Queue"="Transparent""IgnoreProjector"="True""RenderType"="Transparent"}BlendSrcAlphaOneAlphaTestGreater.01ColorMaskRGBCullOffLightingOffZWriteOffFog{Color(0,0,0,0)}SubShader{Pass{CGPROGRAM#pragmavertexvert#pragmafragmentfrag#pragmamulti_compile_particles#include"UnityCG.cginc"sampler2D_MainTex;fixed4_TintColor;float4_Area;structappdata_t{float4vertex:POSITION;fixed4color:COLOR;float2texcoord:TEXCOORD0;};structv2f{float4vertex:SV_POSITION;fixed4color:COLOR;float2texcoord:TEXCOORD0;float2worldPos:TEXCOORD1;};float4_MainTex_ST;v2fvert(appdata_tv){v2fo;o.vertex=mul(UNITY_MATRIX_MVP,v.vertex);o.texcoord=TRANSFORM_TEX(v.texcoord,_MainTex);o.color=v.color;o.worldPos=mul(_Object2World,v.vertex).xy;returno;}fixed4frag(v2fi):SV_Target{boolinArea=i.worldPos.x>=_Area.x&&i.worldPos.x<=_Area.z&&i.worldPos.y>=_Area.y&&i.worldPos.y<=_Area.w;returninArea?2.0f*i.color*_TintColor*tex2D(_MainTex,i.texcoord):fixed4(0,0,0,0);}ENDCG}}}}

如果有需要对shader做改动的,就用这个为范本进行修改吧

大功告成


哦对了,我这里进行了优化,如果Panel尺寸不变并且子对象不会动态添加,可以不用进行重复发送裁切数据,请大家根据自己的情况进行代码修改,如果有以上的情况,将Clip函数的Invoke调用注释打开即可