Unity3D+moba+技能指示器(二)

来源:互联网 发布:淘宝怎样买爱情动作片 编辑:程序博客网 时间:2024/05/28 15:13

2.3指示器图片高亮显示shader

新建shader,代码如下

Shader "Custom/SkillHintBg" {Properties {_MainTex ("Base Texture", 2D) = "white" {}_Color ("Main Color", Color) = (1,1,1,1)  }Category {Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }Blend SrcAlpha OneMinusSrcAlphaCull Off Lighting Off ZWrite Off BindChannels {Bind "Color", colorBind "Vertex", vertexBind "TexCoord", texcoord}SubShader {Pass {//ZTest AlwaysCGPROGRAM   #pragma vertex vert  #pragma fragment frag#include "UnityCG.cginc"   struct v2f {   float4 pos : SV_POSITION;   float2 uv : TEXCOORD0;   };   v2f vert(appdata_tan v)   {   v2f o;   o.pos = mul (UNITY_MATRIX_MVP, v.vertex);  o.uv = v.texcoord; return o;    }   sampler2D _MainTex;  float4 _Color; half4 frag (v2f i) : COLOR   {   half4 result = tex2D (_MainTex, i.uv); result*=_Color;return result; }    ENDCG }Pass {ZTest GreaterCGPROGRAM   #pragma vertex vert  #pragma fragment frag#include "UnityCG.cginc"   struct v2f {   float4 pos : SV_POSITION;   float2 uv : TEXCOORD0;   };   v2f vert(appdata_tan v)   {   v2f o;   o.pos = mul (UNITY_MATRIX_MVP, v.vertex);  o.uv = v.texcoord; return o;    }   sampler2D _MainTex;  float4 _Color; half4 frag (v2f i) : COLOR   {   half4 result = tex2D (_MainTex, i.uv); result*=_Color;result.a /= 3;return result; }    ENDCG }}}}

原来使用的shader


形成的效果


使用高亮shader


2.4 扇形范围指示器

这里是要动态生成一个扇形mesh,通过设置角度和半径达到要显示的效果。动态生成扇形mesh代码如下:

using UnityEngine;using System.Collections;[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]public class MeshFan : MonoBehaviour{    public float radius = 2;    public float angleDegree = 100;    public int segments = 10;    public int angleDegreePrecision = 1000;    public int radiusPrecision = 1000;    private MeshFilter meshFilter;    private SectorMeshCreator creator = new SectorMeshCreator();    private Mesh m_mesh;    [ExecuteInEditMode]    private void Awake()    {        meshFilter = GetComponent<MeshFilter>();    }    private void Update()    {        meshFilter.mesh = creator.CreateMesh(radius, angleDegree, segments, angleDegreePrecision, radiusPrecision);    }    void OnDrawGizmos()    {        Gizmos.color = Color.gray;        DrawMesh();    }    void OnDrawGizmosSelected()    {        Gizmos.color = Color.green;        DrawMesh();    }    private void DrawMesh()    {        Mesh mesh = creator.CreateMesh(radius, angleDegree, segments, angleDegreePrecision, radiusPrecision);        int[] tris = mesh.triangles;        for (int i = 0; i < tris.Length; i += 3)        {            Gizmos.DrawLine(convert2World(mesh.vertices[tris[i]]), convert2World(mesh.vertices[tris[i + 1]]));            Gizmos.DrawLine(convert2World(mesh.vertices[tris[i]]), convert2World(mesh.vertices[tris[i + 2]]));            Gizmos.DrawLine(convert2World(mesh.vertices[tris[i + 1]]), convert2World(mesh.vertices[tris[i + 2]]));        }    }    private Vector3 convert2World(Vector3 src)    {        return transform.TransformPoint(src);    }    private class SectorMeshCreator    {        private float radius;        private float angleDegree;        private int segments;        private Mesh cacheMesh;        /// <summary>        /// 创建一个扇形Mesh        /// </summary>        /// <param name="radius">扇形半价</param>        /// <param name="angleDegree">扇形角度</param>        /// <param name="segments">扇形弧线分段数</param>        /// <param name="angleDegreePrecision">扇形角度精度(在满足精度范围内,认为是同个角度)</param>        /// <param name="radiusPrecision">        /// <pre>        /// 扇形半价精度(在满足半价精度范围内,被认为是同个半价)。        /// 比如:半价精度为1000,则:1.001和1.002不被认为是同个半径。因为放大1000倍之后不相等。        /// 如果半价精度设置为100,则1.001和1.002可认为是相等的。        /// </pre>        /// </param>        /// <returns></returns>        public Mesh CreateMesh(float radius, float angleDegree, int segments, int angleDegreePrecision, int radiusPrecision)        {            if (checkDiff(radius, angleDegree, segments, angleDegreePrecision, radiusPrecision))            {                Mesh newMesh = Create(radius, angleDegree, segments);                if (newMesh != null)                {                    cacheMesh = newMesh;                    this.radius = radius;                    this.angleDegree = angleDegree;                    this.segments = segments;                }            }            return cacheMesh;        }        private Mesh Create(float radius, float angleDegree, int segments)        {            if (segments == 0)            {                segments = 1;#if UNITY_EDITOR                Debug.Log("segments must be larger than zero.");#endif            }            Mesh mesh = new Mesh();            Vector3[] vertices = new Vector3[3 + segments - 1];//全部的顶点数据            vertices[0] = new Vector3(0, 0, 0);            float angle = Mathf.Deg2Rad * angleDegree;            float currAngle = angle / 2;            float deltaAngle = angle / segments;            currAngle = Mathf.Deg2Rad * (90 + angleDegree / 2);            //生成顶点数据            for (int i = 1; i < vertices.Length; i++)            {                vertices[i] = new Vector3(Mathf.Cos(currAngle) * radius, 0, Mathf.Sin(currAngle) * radius);                currAngle -= deltaAngle;            }            //生成三角形数据            int[] triangles = new int[segments * 3];//有segments个三角形,每3个数据构成一个三角形            for (int i = 0, vi = 1; i < triangles.Length; i += 3, vi++)            {                triangles[i] = 0;                triangles[i + 1] = vi;                triangles[i + 2] = vi + 1;            }            mesh.vertices = vertices;            mesh.triangles = triangles;            //纹理坐标            Vector2[] uvs = new Vector2[vertices.Length];            for (int i = 0; i < uvs.Length; i++)            {                uvs[i] = new Vector2(vertices[i].x, vertices[i].z);            }            mesh.uv = uvs;                        return mesh;        }        private bool checkDiff(float radius, float angleDegree, int segments, int angleDegreePrecision, int radiusPrecision)        {            return segments != this.segments || (int)((angleDegree - this.angleDegree) * angleDegreePrecision) != 0 ||                   (int)((radius - this.radius) * radiusPrecision) != 0;        }    }}

Mesh :网格组件,主要用于设置外形和外表。3d模型都是由N个三角形构成,而mesh就是保存描述信息的集合,创建mesh网格:应该按照以下顺序:1)分配顶点2)分配三角形.

如图所示:


生成一个扇形Mesh,由10个小三角形构成。顶点总数数为12.0个顶点坐标为(0,0,0),然后以z轴为正方向,依次计算每个定点坐标。

//生成顶点数据            for (int i = 1; i < vertices.Length; i++)            {                vertices[i] = new Vector3(Mathf.Cos(currAngle) * radius, 0, Mathf.Sin(currAngle) * radius);                currAngle -= deltaAngle;            }

有了所有顶点坐标后,分配三角形。mesh.triangles为一个int[],数量一定是3的倍数,每3个为一组,每个值为索引号到mesh.vertices中找对应的坐标数据。

//生成三角形数据            int[] triangles = new int[segments * 3];//有segments个三角形,每3个数据构成一个三角形            for (int i = 0, vi = 1; i < triangles.Length; i += 3, vi++)            {                triangles[i] = 0;                triangles[i + 1] = vi;                triangles[i + 2] = vi + 1;            }

最后根据技能的施法距离和影响半径设置扇形mesh参数。


2.5选择性技能指示器

这类和扇形一样,就是不需要设置度数,使用一个默认的选择度数,例如60度。当有1个敌人在这个选择扇形的60度之内,他就是目标。如果有多个敌人在范围之内,选取离中心射线夹角最近的。如图所示:

1.当选择指示器的扇形范围内没敌人


2.当选择指示器的扇形范围内有一个敌人,那个选中的敌人头上显示红柱子(后期使用上帝之光来做)


3.当有多个敌人在选择范围内,选择离中心射线最近的


代码如下:

/// <summary>    /// 选择提示器    /// </summary>    /// <param name="skill"></param>    /// <param name="obj"></param>    public UnitCtrl tarSelect(SkillCtrl skill,GameObject obj)    {        UnitCtrl unitSelect = null;        float fRadius = 0.0f;        fRadius = skill.m_disRange;//技能的半径        Vector3 pos = transform.position;        Collider[] bufCollider = Physics.OverlapSphere(pos, fRadius);//获取周围成员        List<UnitCtrl> listUnit = new List<UnitCtrl>();        foreach (var item in bufCollider)        {            UnitCtrl unit = item.GetComponentInParent<UnitCtrl>();            if (unit != null)            {                if (!MainMgr.self.isWe(unit.m_camp) && unit.isAlive && unit.m_isVisible)//非我方,活着,可见                {                    listUnit.Add(unit);                }                }        }        float minDegree = m_selectDegree/2.0f;        //在大圆范围内的再进行筛选  1.满足选择范围夹角,2.离中心射线夹角最小的        foreach (var unit in listUnit)        {            Vector3 unitVec = unit.transform.position - obj.transform.position;            Vector3 selectVec = obj.transform.forward;            float degree = Vector3.Angle(unitVec, selectVec);            if (degree <= minDegree)            {                minDegree = degree;                unitSelect = unit;            }        }        if (unitSelect != null)        {            UIMgr.self.headLockSet(true, unitSelect);        }        else        {            UIMgr.self.headLockSet(false, unitSelect);        }        return unitSelect;}

其中要注意的是选中的红柱子,场景内只能有一个(选中型技能一次只能攻击一个人),当我有选择目标时,设置红柱子的父节点为该目标(实现红柱子在选择范围内跟目标走),当我不存在选择目标,红柱子不激活,并且放回pool池的子节点中。代码如下:

public void headLockSet(bool active,UnitCtrl unit)    {        m_headLock.SetActive(active);        if (active == true)        {            m_headLock.transform.SetParent(unit.transform);            m_headLock.transform.localPosition = new Vector3(0,10,0);            Renderer hintRenderer = m_headLock.GetComponent<Renderer>();            hintRenderer.material.SetColor("_Color", Color.red);        }        else        {            m_headLock.transform.SetParent(m_prefab.transform);            m_headLock.transform.localPosition = new Vector3(0, 0, 0);        }    }



0 0
原创粉丝点击