当前位置:   article > 正文

unity ugui特效实现方式_ugui 图片高亮材质

ugui 图片高亮材质

原理:

        将unity 粒子系统的每个粒子计算颜色,位置,以及uv计算,映射一个长方形内,继承MaskableGraphic类,并重写protected override void OnPopulateMesh(VertexHelper vh)方法,将生成的rect 通过vh.AddUIVertexQuad(_quad);画出。

代码:

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. /// <summary>
  4. /// add by ggr at 2018/07/30
  5. /// UI层的粒子特效,能解决的问题:
  6. /// 1、粒子特效在滚动列表区外裁剪
  7. /// 2、粒子特效层级调整,即可以在夹在任意两个UI元素之间
  8. /// 3、不同分辨率的适配
  9. /// 使用:
  10. /// 主要是特效的美术人员使用。
  11. /// 1、在粒子系统的物体上挂上这个脚本
  12. /// 2、此时会禁用和清空粒子系统的 renderer 模块
  13. /// 3、把材质球拖到脚本上的material字段上
  14. /// </summary>
  15. [ExecuteInEditMode]
  16. [RequireComponent(typeof(CanvasRenderer), typeof(ParticleSystem))]
  17. public class UIParticleSystem : MaskableGraphic
  18. {
  19. [Tooltip("勾上这个,会把粒子系统放在LateUpdate里运行")]
  20. public bool fixedTime = true;
  21. [Range(1, 60)]
  22. public int maxParticleCount = 15;
  23. private Transform _transform;
  24. private ParticleSystem pSystem;
  25. private ParticleSystem.Particle[] particles;
  26. private UIVertex[] _quad = new UIVertex[4];
  27. private Vector4 imageUV = Vector4.zero;
  28. private ParticleSystem.TextureSheetAnimationModule textureSheetAnimation;
  29. private int textureSheetAnimationFrames;
  30. private Vector2 textureSheetAnimationFrameSize;
  31. private ParticleSystemRenderer pRenderer;
  32. private Material currentMaterial;
  33. private Texture currentTexture;
  34. private ParticleSystem.MainModule mainModule;
  35. public override Texture mainTexture
  36. {
  37. get
  38. {
  39. return currentTexture;
  40. }
  41. }
  42. protected bool Initialize()
  43. {
  44. // initialize members
  45. if (_transform == null)
  46. {
  47. _transform = transform;
  48. }
  49. if (pSystem == null)
  50. {
  51. pSystem = GetComponent<ParticleSystem>();
  52. if (pSystem == null)
  53. {
  54. return false;
  55. }
  56. mainModule = pSystem.main;
  57. //最大存活粒子数限制为15,不要太大,影响效率
  58. if (pSystem.main.maxParticles > maxParticleCount)
  59. {
  60. mainModule.maxParticles = maxParticleCount;
  61. }
  62. pRenderer = pSystem.GetComponent<ParticleSystemRenderer>();
  63. if (pRenderer != null)
  64. {
  65. pRenderer.material = null;
  66. pRenderer.enabled = false;
  67. }
  68. currentMaterial = material;
  69. if (currentMaterial && currentMaterial.HasProperty("_MainTex"))
  70. {
  71. currentTexture = currentMaterial.mainTexture;
  72. if (currentTexture == null)
  73. currentTexture = Texture2D.whiteTexture;
  74. }
  75. material = currentMaterial;
  76. // automatically set scaling
  77. mainModule.scalingMode = ParticleSystemScalingMode.Hierarchy;
  78. particles = null;
  79. }
  80. if (particles == null)
  81. particles = new ParticleSystem.Particle[pSystem.main.maxParticles];
  82. imageUV = new Vector4(0, 0, 1, 1);
  83. // prepare texture sheet animation
  84. textureSheetAnimation = pSystem.textureSheetAnimation;
  85. textureSheetAnimationFrames = 0;
  86. textureSheetAnimationFrameSize = Vector2.zero;
  87. if (textureSheetAnimation.enabled)
  88. {
  89. textureSheetAnimationFrames = textureSheetAnimation.numTilesX * textureSheetAnimation.numTilesY;
  90. textureSheetAnimationFrameSize = new Vector2(1f / textureSheetAnimation.numTilesX, 1f / textureSheetAnimation.numTilesY);
  91. }
  92. return true;
  93. }
  94. protected override void Awake()
  95. {
  96. base.Awake();
  97. if (!Initialize())
  98. enabled = false;
  99. //不需要响应事件
  100. raycastTarget = false;
  101. }
  102. protected override void OnPopulateMesh(VertexHelper vh)
  103. {
  104. #if UNITY_EDITOR
  105. if (!Application.isPlaying)
  106. {
  107. if (!Initialize())
  108. {
  109. return;
  110. }
  111. }
  112. #endif
  113. // prepare vertices
  114. vh.Clear();
  115. if (!gameObject.activeInHierarchy)
  116. {
  117. return;
  118. }
  119. Vector2 temp = Vector2.zero;
  120. Vector2 corner1 = Vector2.zero;
  121. Vector2 corner2 = Vector2.zero;
  122. // iterate through current particles
  123. int count = pSystem.GetParticles(particles);
  124. for (int i = 0; i < count; ++i)
  125. {
  126. ParticleSystem.Particle particle = particles[i];
  127. // get particle properties
  128. Vector2 position = (mainModule.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
  129. float rotation = -particle.rotation * Mathf.Deg2Rad;
  130. float rotation90 = rotation + Mathf.PI / 2;
  131. Color32 color = particle.GetCurrentColor(pSystem);
  132. float size = particle.GetCurrentSize(pSystem) * 0.5f;
  133. // apply scale
  134. if (mainModule.scalingMode == ParticleSystemScalingMode.Shape)
  135. position /= canvas.scaleFactor;
  136. // apply texture sheet animation
  137. Vector4 particleUV = imageUV;
  138. if (textureSheetAnimation.enabled)
  139. {
  140. float frameProgress = 1 - (particle.remainingLifetime / particle.startLifetime);
  141. if (textureSheetAnimation.frameOverTime.curveMin != null)
  142. {
  143. frameProgress = textureSheetAnimation.frameOverTime.curveMin.Evaluate(1 - (particle.remainingLifetime / particle.startLifetime));
  144. }
  145. else if (textureSheetAnimation.frameOverTime.curve != null)
  146. {
  147. frameProgress = textureSheetAnimation.frameOverTime.curve.Evaluate(1 - (particle.remainingLifetime / particle.startLifetime));
  148. }
  149. else if (textureSheetAnimation.frameOverTime.constant > 0)
  150. {
  151. frameProgress = textureSheetAnimation.frameOverTime.constant - (particle.remainingLifetime / particle.startLifetime);
  152. }
  153. frameProgress = Mathf.Repeat(frameProgress * textureSheetAnimation.cycleCount, 1);
  154. int frame = 0;
  155. switch (textureSheetAnimation.animation)
  156. {
  157. case ParticleSystemAnimationType.WholeSheet:
  158. frame = Mathf.FloorToInt(frameProgress * textureSheetAnimationFrames);
  159. break;
  160. case ParticleSystemAnimationType.SingleRow:
  161. frame = Mathf.FloorToInt(frameProgress * textureSheetAnimation.numTilesX);
  162. int row = textureSheetAnimation.rowIndex;
  163. frame += row * textureSheetAnimation.numTilesX;
  164. break;
  165. }
  166. frame %= textureSheetAnimationFrames;
  167. particleUV.x = (frame % textureSheetAnimation.numTilesX) * textureSheetAnimationFrameSize.x;
  168. particleUV.y = Mathf.FloorToInt(frame / textureSheetAnimation.numTilesX) * textureSheetAnimationFrameSize.y;
  169. particleUV.z = particleUV.x + textureSheetAnimationFrameSize.x;
  170. particleUV.w = particleUV.y + textureSheetAnimationFrameSize.y;
  171. }
  172. temp.x = particleUV.x;
  173. temp.y = particleUV.y;
  174. _quad[0] = UIVertex.simpleVert;
  175. _quad[0].color = color;
  176. _quad[0].uv0 = temp;
  177. temp.x = particleUV.x;
  178. temp.y = particleUV.w;
  179. _quad[1] = UIVertex.simpleVert;
  180. _quad[1].color = color;
  181. _quad[1].uv0 = temp;
  182. temp.x = particleUV.z;
  183. temp.y = particleUV.w;
  184. _quad[2] = UIVertex.simpleVert;
  185. _quad[2].color = color;
  186. _quad[2].uv0 = temp;
  187. temp.x = particleUV.z;
  188. temp.y = particleUV.y;
  189. _quad[3] = UIVertex.simpleVert;
  190. _quad[3].color = color;
  191. _quad[3].uv0 = temp;
  192. if (rotation == 0)
  193. {
  194. // no rotation
  195. corner1.x = position.x - size;
  196. corner1.y = position.y - size;
  197. corner2.x = position.x + size;
  198. corner2.y = position.y + size;
  199. temp.x = corner1.x;
  200. temp.y = corner1.y;
  201. _quad[0].position = temp;
  202. temp.x = corner1.x;
  203. temp.y = corner2.y;
  204. _quad[1].position = temp;
  205. temp.x = corner2.x;
  206. temp.y = corner2.y;
  207. _quad[2].position = temp;
  208. temp.x = corner2.x;
  209. temp.y = corner1.y;
  210. _quad[3].position = temp;
  211. }
  212. else
  213. {
  214. // apply rotation
  215. Vector2 right = new Vector2(Mathf.Cos(rotation), Mathf.Sin(rotation)) * size;
  216. Vector2 up = new Vector2(Mathf.Cos(rotation90), Mathf.Sin(rotation90)) * size;
  217. _quad[0].position = position - right - up;
  218. _quad[1].position = position - right + up;
  219. _quad[2].position = position + right + up;
  220. _quad[3].position = position + right - up;
  221. }
  222. vh.AddUIVertexQuad(_quad);
  223. }
  224. }
  225. void Update()
  226. {
  227. if (!fixedTime && Application.isPlaying)
  228. {
  229. pSystem.Simulate(Time.unscaledDeltaTime, false, false, true);
  230. SetAllDirty();
  231. if ((currentMaterial != null && currentTexture != currentMaterial.mainTexture) ||
  232. (material != null && currentMaterial != null && material.shader != currentMaterial.shader))
  233. {
  234. pSystem = null;
  235. Initialize();
  236. }
  237. }
  238. }
  239. void LateUpdate()
  240. {
  241. if (!Application.isPlaying)
  242. {
  243. SetAllDirty();
  244. }
  245. else
  246. {
  247. if (fixedTime)
  248. {
  249. pSystem.Simulate(Time.unscaledDeltaTime, false, false, true);
  250. SetAllDirty();
  251. if ((currentMaterial != null && currentTexture != currentMaterial.mainTexture) ||
  252. (material != null && currentMaterial != null && material.shader != currentMaterial.shader))
  253. {
  254. pSystem = null;
  255. Initialize();
  256. }
  257. }
  258. }
  259. if (material == currentMaterial)
  260. return;
  261. pSystem = null;
  262. Initialize();
  263. }
  264. }

 

shader:

  1. Shader "17zuoye/UI Particle Addtive"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Sprite Texture", 2D) = "white" {}
  6. _Color ("Tint", Color) = (0.5,0.5,0.5,0.5)
  7. _SpeedU("横向速度", float) = 0
  8. _SpeedV("纵向速度", float) = 0
  9. _ColorAdd("亮度",float) = 2
  10. _StencilComp ("Stencil Comparison", Float) = 8
  11. _Stencil ("Stencil ID", Float) = 0
  12. _StencilOp ("Stencil Operation", Float) = 0
  13. _StencilWriteMask ("Stencil Write Mask", Float) = 255
  14. _StencilReadMask ("Stencil Read Mask", Float) = 255
  15. _ColorMask ("Color Mask", Float) = 15
  16. [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
  17. }
  18. SubShader
  19. {
  20. Tags
  21. {
  22. "Queue"="Transparent"
  23. "IgnoreProjector"="True"
  24. "RenderType"="Transparent"
  25. "PreviewType"="Plane"
  26. "CanUseSpriteAtlas"="True"
  27. }
  28. Stencil
  29. {
  30. Ref [_Stencil]
  31. Comp [_StencilComp]
  32. Pass [_StencilOp]
  33. ReadMask [_StencilReadMask]
  34. WriteMask [_StencilWriteMask]
  35. }
  36. Cull Off
  37. Lighting Off
  38. ZWrite Off
  39. ZTest [unity_GUIZTestMode]
  40. Blend SrcAlpha one
  41. ColorMask [_ColorMask]
  42. Pass
  43. {
  44. Name "Default"
  45. CGPROGRAM
  46. #pragma vertex vert
  47. #pragma fragment frag
  48. #pragma target 2.0
  49. #include "UnityCG.cginc"
  50. #include "UnityUI.cginc" // 2D Mask 剪裁。
  51. #pragma multi_compile __ UNITY_UI_CLIP_RECT
  52. #pragma multi_compile __ UNITY_UI_ALPHACLIP
  53. struct appdata_t
  54. {
  55. float4 vertex : POSITION;
  56. float4 color : COLOR;
  57. float2 texcoord : TEXCOORD0;
  58. UNITY_VERTEX_INPUT_INSTANCE_ID
  59. };
  60. struct v2f
  61. {
  62. float4 vertex : SV_POSITION;
  63. fixed4 color : COLOR;
  64. float2 uv : TEXCOORD0;
  65. float4 worldPosition : TEXCOORD1; // 2D Mask 剪裁。
  66. UNITY_VERTEX_OUTPUT_STEREO
  67. };
  68. sampler2D _MainTex;
  69. float4 _MainTex_ST;
  70. fixed4 _Color;
  71. fixed4 _TextureSampleAdd;
  72. float4 _ClipRect; // 2D Mask 剪裁。
  73. float _SpeedU;
  74. float _SpeedV;
  75. float _ColorAdd;
  76. v2f vert(appdata_t v)
  77. {
  78. v2f OUT;
  79. UNITY_SETUP_INSTANCE_ID(v);
  80. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
  81. OUT.worldPosition = v.vertex; // 2D Mask 剪裁。
  82. OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
  83. OUT.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
  84. OUT.uv.xy += float2(_SpeedU, _SpeedV ) * _Time.x;
  85. OUT.color = v.color;
  86. return OUT;
  87. }
  88. fixed4 frag(v2f IN) : SV_Target
  89. {
  90. fixed4 albedo = tex2D(_MainTex, IN.uv);
  91. fixed4 color = _ColorAdd * IN.color * _Color * albedo;
  92. #ifdef UNITY_UI_CLIP_RECT
  93. color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); // 2D Mask 剪裁。
  94. #endif
  95. #ifdef UNITY_UI_ALPHACLIP
  96. clip (color.a - 0.001);
  97. #endif
  98. return color;
  99. }
  100. ENDCG
  101. }
  102. }
  103. }

原作地址:https://forum.unity.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/660340
推荐阅读
相关标签
  

闽ICP备14008679号