最近学Shader有点心得,做了一个SLG画线模块。
性能有能再提高的地方,欢迎大佬指点。
1.介绍
- 画线模块,可用于SLG游戏行军线。
- 多个不同速度、颜色、长度的线在一个DrawCall中实现。
- 材质中ShowLength控制两端显示的长度,AlphaLength控制渐隐长度,AllShowLength是一个临界值,长度小于它的线全部显示,长度大于它的线出现中间渐隐消失效果。(ShowLength、AlphaLength控制这两个效果)
- 只有一个C#脚本文件和一个Shader,100多行代码。
2.使用demo
- 画线:int handle=LineManager.Instance.DrawLine(Vector3 start,Vector3 end,Color color,float speed);
- 回收线:LineManager.Instance.BackLine(int handle);
多次调用画线效果:
- 线中间不显示,两端渐隐
- 线全部显示
3.C#代码部分
- using System.Collections.Generic;
- using UnityEngine;
- using LineHandle = System.Int32;
- class LineManager
- {
- private GameObject m_root = null;
- private GameObject m_origin = null;
- private Stack<GameObject> m_linePool = null;
- private Dictionary<int, GameObject> m_drawLines = null;
- private int m_index = 0;
- #region 外部接口
- //参数:起始点、终止点、颜色、速度
- public LineHandle DrawLine(www.078881.cn Vector3 start,Vector3 end,Color color,float speed)
- {
- //从池中拿出
- GameObject line = getFromPool();
- Transform lineTransform = line.transform;
- Transform childTransform = lineTransform.GetChild(0);
- Mesh mesh = childTransform.GetComponent<MeshFilter>().mesh;
- var vertices = mesh.vertices;
- //设置颜色
- var colors = new Color[vertices.Length];
- for (int i = 0; i < colors.Length; i++)
- {
- colors[i] = color;
- }
- mesh.colors = colors;
- //设置浮transform位置朝向,子transform缩放
- Vector3 position = new Vector3((www.leyou2.net/ start.x+end.x)/2,(start.y+end.y)/2,(start.z+end.z)/2);
- Vector3 scale =new Vector3(1,Vector3.Distance(start,end),1);
- Vector3 direction = (end - start).normalized;
- lineTransform.localPosition www.yongshiyule178.com= position;
- childTransform.localScale = scale;
- lineTransform.localRotation =www.meiwanyule.cn Quaternion.LookRotation(direction);
- //设置Y轴缩放,速度值
- var uv2 = new Vector2[vertices.Length];
- for (int i = 0; i < uv2.Length; i++)
- {
- uv2[i] = new Vector2(childTransform.localScale.y / childTransform.localScale.x, speed);
- }
- mesh.uv2 = uv2;
- //放入字典
- m_drawLines.Add(++m_index, line);
- return m_index;
- }
- //参数:索引
- public void BackLine(LineHandle handle)
- {
- if(m_drawLines.ContainsKey(handle))
- {
- GameObject line = m_drawLines[handle];
- m_drawLines.Remove( www.leyouzaixian2.com handle);
- backToPool(line);
- }
- }
- #endregion
- #region 内部实现
- private void Init()
- {
- m_origin = Resources.Load("DrawLine/Line") as GameObject;
- m_linePool = new Stack<GameObject>(23);
- m_root = new GameObject("LineRoot");
- m_drawLines = new Dictionary<int, GameObject>(23);
- m_index = 0;
- }
- private GameObject getFromPool()
- {
- if (m_linePool.Count==0)
- {
- GameObject gameObject = GameObject.Instantiate(m_origin);
- gameObject.transform.parent = m_root.transform;
- return gameObject;
- }
- else
- {
- return m_linePool.Pop();
- }
- }
- private void backToPool(GameObject line)
- {
- line.transform.localPosition = new Vector3(1000,1000,1000);
- m_linePool.Push(line);
- }
- #endregion
- #region singleton
- private static LineManager _instance = null;
- private LineManager() { Init(); }
- public static LineManager Instance
- {
- get {
- if (_instance==null)
- {
- _instance = new LineManager();
- }
- return _instance;
- }
- private set { }
- }
- #endregion
- }
4.Shader代码部分
-
- Shader "lineShader"{
- Properties
- {
- _MainTex("Line Texture",2D) = "white"{}
- _ShowLength("Show Length",Float)=6.0 //展现的长度
- _AlphaLength("Alpha Length",Float)=5.0 //有透明效果的长度
- _AllShowLength("AllShow Length",Float)=10 //临界值,如果线比它短,那么全都显示
- }
- SubShader{
- Tags{ "Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" }
- Pass
- {
- Tags{ "LightMode" = "ForwardBase" }
- ZWrite Off
- Blend SrcAlpha OneMinusSrcAlpha
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #include "Lighting.cginc"
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _ShowLength;
- float _AlphaLength;
- float _AllShowLength;
- struct a2v
- {
- float4 vertex:POSITION;
- float4 texcoord:TEXCOORD0;
- fixed4 color:COLOR0;
- float2 uv2 : TEXCOORD1; //第二套UV:x分量存储y轴缩放,y分量存储滚动速度
- };
- struct v2f
- {
- float4 pos:SV_POSITION;
- float2 uv:TEXCOORD1;
- fixed4 color:COLOR1;
- float2 uv2:TEXCOORD2; //x分量存储Y轴缩放固定值,y分量存储滚动前uv.y
- };
- v2f vert(a2v v)
- {
- v2f o;
- o.pos = UnityObjectToClipPos(v.vertex);
- o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex);
- o.uv.y *=v.uv2.x;//Y轴缩放
- o.color=v.color;
- o.uv2=o.uv;
- o.uv2.x=v.uv2.x; //o.uv2.x存储Y轴缩放固定值,y轴当前uv.y
- o.uv.y -=v.uv2.y* _Time.z; //Y轴随时间偏移
- return o;
- }
- fixed4 frag(v2f i) :SV_Target
- {
- fixed4 color = tex2D(_MainTex,i.uv.xy);
- //后半段透明值与前半段透明值,取最大值
- i.color.a=max(clamp((_ShowLength-(i.uv2.x-i.uv2.y))/_AlphaLength,0,1),clamp((_ShowLength-i.uv2.y)/_AlphaLength,0,1)); //i.uv2.y存储此片元的UV.y
- //当比_AllShowLength小的时候全部显示
- i.color.a+=clamp(_AllShowLength-i.uv2.x,0,1); //大于0
- i.color.a *= color.a;
- return i.color;
- }
- ENDCG
- }
- }
- //Fallback "VertexLit"
- }