之前做过一个流光效果(http://www.cnblogs.com/jietian331/p/4748644.html)。
现将其改进一下,与NGUI结合起来,提供一个具有流光效果的组件:UIWalkLightSprite。
效果如图:
首先是此组件的源码,如下:
1 using System; 2 using UnityEngine; 3 4 /// <summary> 5 /// 具有流光效果的 UISprite。 6 /// 注意: 7 /// 1. 流光图片需命名为"Special_WalkLight"(待改善) 8 /// 2. 流光的 UISprite 暂不支持 UIPanel 剪裁(待改善) 9 /// 3. 设置 UISprite 的 color 将无效 10 /// </summary> 11 public class UIWalkLightSprite : UISprite 12 { 13 const string WalkLightShaderName = "Bleach/Walk Light Colored"; 14 15 float m_duration = 2f; 16 float m_widthLight2Sprite; 17 float m_timer; 18 float m_t1; 19 bool m_initedMat = true; 20 Vector2 m_lightURange; 21 22 void Awake() 23 { 24 // replace shader 25 if (base.atlas.spriteMaterial.shader.name != WalkLightShaderName) 26 { 27 string tempAtlasName = string.Format("[WalkLightTempAtlas_{0}]", atlas.name); 28 Transform t = transform.Find(tempAtlasName); 29 if (t == null) 30 t = ((GameObject)GameObject.Instantiate(atlas.gameObject)).transform; 31 32 t.gameObject.SetActive(false); 33 t.name = tempAtlasName; 34 t.parent = transform; 35 36 var tempAtlas = t.GetComponent<UIAtlas>(); 37 if (tempAtlas.spriteMaterial.name != WalkLightShaderName) 38 { 39 Material mat = (Material)GameObject.Instantiate(atlas.spriteMaterial); 40 mat.shader = Shader.Find(WalkLightShaderName); 41 tempAtlas.spriteMaterial = mat; 42 } 43 44 base.atlas = tempAtlas; 45 } 46 } 47 48 public override void OnFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols) 49 { 50 base.OnFill(verts, uvs, cols); 51 52 // set uv2 to vertex 53 var lightSprite = atlas.GetSprite("Special_WalkLight"); 54 Rect lightOuter = new Rect(lightSprite.x, lightSprite.y, lightSprite.width, lightSprite.height); 55 lightOuter = NGUIMath.ConvertToTexCoords(lightOuter, mainTexture.width, mainTexture.height); 56 57 // 用 color 把流光图片的 uv 地址传到 shader 中,故会导致设置 color 无效 58 cols.Clear(); 59 cols.Add(new Color(lightOuter.xMin, lightOuter.yMin, 0)); 60 cols.Add(new Color(lightOuter.xMin, lightOuter.yMax, 0)); 61 cols.Add(new Color(lightOuter.xMax, lightOuter.yMax, 0)); 62 cols.Add(new Color(lightOuter.xMax, lightOuter.yMin, 0)); 63 64 // data set to shader 65 m_initedMat = false; 66 m_lightURange = new Vector2(lightOuter.xMin, lightOuter.xMax); 67 68 Rect spriteOuter = new Rect(mSprite.x, mSprite.y, mSprite.width, mSprite.height); 69 spriteOuter = NGUIMath.ConvertToTexCoords(spriteOuter, mainTexture.width, mainTexture.height); 70 m_widthLight2Sprite = (lightOuter.width * spriteOuter.height) / (lightOuter.height * spriteOuter.width); 71 m_t1 = (1 - m_widthLight2Sprite) * m_duration; 72 } 73 74 protected override void OnUpdate() 75 { 76 base.OnUpdate(); 77 78 if (RendererMat != null) 79 { 80 if (!m_initedMat) 81 { 82 m_initedMat = true; 83 84 // init 85 RendererMat.SetFloat("_LightWidthToMain", m_widthLight2Sprite); 86 RendererMat.SetVector("_LightURange", m_lightURange); 87 } 88 89 // 驱动流光动画 90 RendererMat.SetFloat("_TimeRate", m_timer / m_duration); 91 92 m_timer += Time.deltaTime; 93 94 if (m_timer > m_duration) 95 m_timer = 0; 96 else if (m_timer > m_t1) 97 RendererMat.SetFloat("_ReachBoundary", 1); 98 else 99 RendererMat.SetFloat("_ReachBoundary", -1); 100 } 101 } 102 103 Material RendererMat 104 { 105 get { return base.Renderer != null ? base.Renderer.sharedMaterial : null; } 106 } 107 108 public float Duration 109 { 110 set 111 { 112 if (value <= 0) 113 throw new ArgumentException("value <= 0"); 114 115 m_duration = value; 116 m_t1 = (1 - m_widthLight2Sprite) * m_duration; 117 } 118 } 119 }