【游戲】UI層粒子特效存在的問題及解決方案
一,UI層粒子特效存在的問題
1.粒子特效的裁剪問題。某種滑動出滾動列表后被裁剪
2.粒子特效與UI元素之間的層級問題。能夠被某些UI元素遮蓋,或夾在某些UI元素之間
3.粒子特效的適應問題。在不同分辨率下粒子特效不能像UI一樣自動適應
這些問題所有人都遇到過,解決方案也是多種多樣,本博客提出一個統一的解決方案,能夠同時解決以上3個問題。
二,解決方案
自己實現一套UI層的粒子系統,即粒子系統發射的每個粒子都是一個UI元素,這樣就可以不用做任何事情,以上問題就可以迎刃而解。
廢話不多說,直接上代碼:
使用UnityEngine;
使用UnityEngine.UI;
/// <summary>
///由ggr在2018/07/30添加
//// UI層的粒子特效,能解決的問題:
/// 1,粒子特效在滾動列表區外裁剪
//// 2,粒子特效層級調整,即可以在夾在任意兩個UI元素之間
/// 3,不同分辨率的適應
/// /使用:
///主要是特效的美術人員使用。///
1,在粒子系統的物體上掛上這個腳本
/// 2,此時會替換和清空粒子系統的渲染器模塊
/// 3,把材質球拖到腳本上的材質頂部上
/// </ summary>
[ExecuteInEditMode ]
[RequireComponent(typeof(CanvasRenderer),typeof(ParticleSystem))]公共類UIParticleSystem:MaskableGraphic {[Tooltip(“勾上這個,會把粒子系統放在LateUpdate里運行”)] public bool fixedTime = true; [Range(1,60)] public int maxParticleCount = 15;
private Transform _transform;
專用ParticleSystem pSystem;
私有ParticleSystem.Particle []粒子;
私有UIVertex [] _quad =新的UIVertex [4];
私有Vector4 imageUV = Vector4.zero;
私有ParticleSystem.TextureSheetAnimationModule textureSheetAnimation;
私人詮釋textureSheetAnimationFrames;
私有Vector2 textureSheetAnimationFrameSize;
專用的ParticleSystemRenderer pRenderer;
私人物質當前材料;
private Texture currentTexture;
私有ParticleSystem.MainModule mainModule;
公共重寫Texture mainTexture {
get {
return currentTexture;
}
}
受保護的布爾Initialize(){
如果(_transform == null){_
transform =變換;
}
if(pSystem == null){
pSystem = GetComponent <ParticleSystem>();
if(pSystem == null){
返回false;
}
mainModule = pSystem.main;
如果(pSystem.main.maxParticles> maxParticleCount){
mainModule.maxParticles = maxParticleCount;
}
pRenderer = pSystem.GetComponent <ParticleSystemRenderer>();
如果(pRenderer!= null){
pRenderer.material = null;
pRenderer.enabled = false;
}
currentMaterial =材料;
如果(currentMaterial && currentMaterial.HasProperty(“ _ MainTex”)){
currentTexture = currentMaterial.mainTexture;
如果(currentTexture == null)currentTexture = Texture2D.whiteTexture;
}
material = currentMaterial;
mainModule.scalingMode = ParticleSystemScalingMode.Hierarchy;
粒子= null;
}
如果(粒子==空)粒子=新的ParticleSystem.Particle [pSystem.main.maxParticles];
imageUV =新的Vector4(0,0,1,1);
textureSheetAnimation = pSystem.textureSheetAnimation;
textureSheetAnimationFrames = 0;
textureSheetAnimationFrameSize = Vector2.zero;
如果(textureSheetAnimation.enabled){
textureSheetAnimationFrames = textureSheetAnimation.numTilesX * textureSheetAnimation.numTilesY;
textureSheetAnimationFrameSize = new Vector2(1f / textureSheetAnimation.numTilesX,1f / textureSheetAnimation.numTilesY);
}
返回true;
}
受保護的重寫void Awake(){
base.Awake();
如果(!Initialize())enabled = false;
raycastTarget = false;
}
受保護的重寫void OnPopulateMesh(VertexHelper vh){#
如果為UNITY_EDITOR,
如果(!Application.isPlaying){
如果(!Initialize()){
返回;
}
} #ENDIF
vh.Clear();
如果(!gameObject.activeInHierarchy){
返回;
}
Vector2 temp = Vector2.zero;
Vector2 corner1 = Vector2.zero;
Vector2 corner2 = Vector2.zero;
int count = pSystem.GetParticles(particles);
for(int i = 0; i <count; i){
粒子系統。粒子粒子=粒子[i];
Vector2位置=(mainModule.simulationSpace == ParticleSystemSimulationSpace.Local?Particle.position:_transform.InverseTransformPoint(particle.position));
浮點旋轉= -particle.rotation * Mathf.Deg2Rad;
浮點旋轉90 =旋轉Mathf.PI / 2;
Color32 color =粒子.GetCurrentColor(pSystem);
浮點尺寸=粒子.GetCurrentSize(pSystem)* 0.5f;
如果(mainModule.scalingMode == ParticleSystemScalingMode.Shape)position / = canvas.scaleFactor;
Vector4粒子UV =圖像UV;
如果(textureSheetAnimation.enabled){
float frameProgress = 1-(particle.remainingLifetime / particle.startLifetime);
如果(textureSheetAnimation.frameOverTime.curveMin!= null){
frameProgress = textureSheetAnimation.frameOverTime.curveMin.Evaluate(1-(particle.remainingLifetime / particle.startLifetime));
}否則if(textureSheetAnimation.frameOverTime.curve!= null){
frameProgress = textureSheetAnimation.frameOverTime.curve.Evaluate(1-(particle.remainingLifetime / particle.startLifetime));;
}否則if(textureSheetAnimation.frameOverTime.constant> 0){
frameProgress = textureSheetAnimation.frameOverTime.constant-(particle.remainingLifetime / particle.startLifetime);
}
frameProgress = Mathf.Repeat(frameProgress * textureSheetAnimation.cycleCount,1);
int幀= 0;
開關(textureSheetAnimation.animation){
案例ParticleSystemAnimationType.WholeSheet:
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimationFrames);
休息;
案例ParticleSystemAnimationType.SingleRow:
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimation.numTilesX);
int row = textureSheetAnimation.rowIndex;
框架=行* textureSheetAnimation.numTilesX;
休息;
}
框架%= textureSheetAnimationFrames;
particleUV.x =(幀%textureSheetAnimation.numTilesX)* textureSheetAnimationFrameSize.x;
particleUV.y = Mathf.FloorToInt(frame / textureSheetAnimation.numTilesX)* textureSheetAnimationFrameSize.y;
particleUV.z =粒子UV.x textureSheetAnimationFrameSize.x;
particleUV.w =粒子UV.y textureSheetAnimationFrameSize.y;
}
temp.x =粒子UV.x;
temp.y =粒子UV.y;
_quad [0] = UIVertex.simpleVert;
_quad [0] .color =顏色;
_quad [0] .uv0 = temp;
temp.x =粒子UV.x;
temp.y =粒子UV.w;
_quad [1] = UIVertex.simpleVert;
_quad [1] .color =顏色;
_quad [1] .uv0 = temp;
temp.x =粒子UV.z;
temp.y =粒子UV.w;
_quad [2] = UIVertex.simpleVert;
_quad [2] .color =顏色;
_quad [2] .uv0 = temp;
temp.x =粒子UV.z;
temp.y =粒子UV.y;
_quad [3] = UIVertex.simpleVert;
_quad [3] .color =顏色;
_quad [3] .uv0 = temp;
if(rotation == 0){
corner1.x = position.x-大小;
corner1.y = position.y-大小;
corner2.x = position.x大小;
corner2.y = position.y大小;
temp.x = corner1.x;
temp.y = corner1.y;
_quad [0] .position = temp;
temp.x = corner1.x;
temp.y = corner2.y;
_quad [1] .position = temp;
temp.x = corner2.x;
temp.y = corner2.y;
_quad [2] .position = temp;
temp.x = corner2.x;
temp.y = corner1.y;
_quad [3] .position = temp;
} 別的 {
右邊的Vector2 =新的Vector2(Mathf.Cos(旋轉),Mathf.Sin(旋轉))*大小;
Vector2 up =新Vector2(Mathf.Cos(rotation90),Mathf.Sin(rotation90))*大小;
_quad [0] .position =位置-右-上;
_quad [1] .position =位置-右上;
_quad [2] .position =右上角的位置;
_quad [3] .position =位置右-向上;
}
vh.AddUIVertexQuad(_quad);
}
}
void Update(){
if(!fixedTime && Application.isPlaying){
pSystem.Simulate(Time.unscaledDeltaTime,false,false,true);
SetAllDirty();
if(((currentMaterial!= null && currentTexture!= currentMaterial.mainTexture)||(material!= null && currentMaterial!= null && material.shader!= currentMaterial.shader)){
pSystem = null;
初始化();
}
}
}
void LateUpdate(){
如果(!Application.isPlaying){
SetAllDirty();
} else {
if(fixedTime){
pSystem.Simulate(Time.unscaledDeltaTime,false,false,true);
SetAllDirty();
if(((currentMaterial!= null && currentTexture!= currentMaterial.mainTexture)||(material!= null && currentMaterial!= null && material.shader!= currentMaterial.shader)){
pSystem = null;
初始化();
}
}
}
如果(材料== currentMaterial)回報;
pSystem = null;
初始化();
}
}
還需要一個shader,這里我就直接拿的UI Default的shader,只是混合公式我改變成Blend SrcAlpha one,即粒子的重疊模式
代碼:
著色器“ 17zuoye / UI粒子添加劑” {
屬性{
_MainTex(“ Sprite Texture”,2D)=“ white” {}
_Color(“ Tint”,Color)=(0.5,0.5,0.5,0.5)
_StencilComp(“模板比較”,浮點數)= 8 _Stencil(“模板ID”,浮點數)= 0 _StencilOp(“模板操作”,浮點數)= 0 _StencilWriteMask(“模板寫屏蔽”,浮點數)= 255 _StencilReadMask(“ S掩碼”,浮點數)= 255
_ColorMask(“ Color Mask”,Float)= 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip(“使用Alpha剪輯”,浮動)= 0
}
SubShader {
標簽{
“ Queue” =“ Transparent”“ IgnoreProjector” =“ True”“ RenderType” =“ Transparent”“ PreviewType” =“平面”“ CanUseSpriteAtlas” =“ True”
}
模具{
Ref [_Stencil] Comp [_StencilComp] Pass [_StencilOp] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask]
}
取消照明關閉ZWrite Off ZTest [unity_GUIZTestMode]混合SrcAlpha一種ColorMask [_ColorMask]
傳遞{
名稱“默認” CGPROGRAM#pragma頂點vert#pragma片段frag#pragma目標2.0
#include“ UnityCG.cginc” #include“ UnityUI.cginc” // 2D Mask剪裁。
#pragma multi_compile __ UNITY_UI_CLIP_RECT#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t {
float4頂點:POSITION float4顏色:COLOR float2 texcoord:TEXCOORD0 UNITY_VERTEX_INPUT_INSTANCE_ID
}
struct v2f {
float4頂點:SV_POSITION fixed4顏色:COLOR float2 texcoord:TEXCOORD0 float4 worldPosition:TEXCOORD1 UNITY_VERTEX_OUTPUT_STEREO
}
fixed4 _Color fixed4 _TextureSampleAdd float4 _ClipRect
v2f vert(appdata_t v){
v2f OUT UNITY_SETUP_INSTANCE_ID(v)UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT)OUT.worldPosition = v.vertex OUT.vertex = UnityObjectToClipPos(OUT.worldPosition)
OUT.texcoord = v.texcoord
OUT.color = v.color
return OUT
}
sampler2D _MainTex
fixed4 frag(v2f IN):SV_Target {
fixed4 albedo = tex2D(_MainTex,IN.texcoord)
fixed4 color = 2.0f * IN.color * _Color * albedo#ifdef UNITY_UI_CLIP_RECT color.a * = UnityGet2DClipping(IN.worldPosition.xy,_ClipRect)#endif
#ifdef UNITY_UI_ALPHACLIP剪輯(color.a-0.001)#endif
返回顏色
}
ENDCG
}
}
}
三,驗證
1,裁剪
2,層級
3,適應
四,使用
轉載聲明:本文涉及網絡,不作任何商業用途。

全部評論


暫無留言,趕緊搶占沙發
熱門資訊

你心中的打虎英雄是怎樣的?第十三屆王座杯現面向全國征稿~...

今年剛高中畢業的畫師,被米山舞稱贊作品有獨特性...

繪學霸訂單服務協議V1.1.0

畢業學員采訪丨王氏教育學生,牛的!

28歲學什么技術可以從頭再來?

無編程平臺Core有多猛?玩家自創2萬款UE游戲...

轉行做什么工作比較好?

王座杯比賽答疑,快來GET正確交稿姿勢!

適合初中女生讀的技校專業有哪些?
