zoukankan      html  css  js  c++  java
  • 扇形技能指示器

    扇形技能指示器

    网上基本有两种方法写扇形指示器:

    1. 生成Mesh拼接
    2. Shader绘制

    Mesh拼接

    我这边用Unity自带的Gizmos简单的绘制一下Mesh

    注意:Gizmos.DrawMesh()中的Mesh必须包含vertices和normals

    生成vertices

    /// <summary>
    /// 生成vertices
    /// </summary>
    /// <param name="precision">三角形数量</param>
    /// <param name="originPos">原点</param>
    /// <param name="forward">朝向</param>
    /// <returns>vertuces</returns>
    private Vector3[] GetVectors(int precision, Vector3 originPos, Vector3 forward)
    {
        // 一共需要三角形数量+2的顶点数
        Vector3[] meshVectors = new Vector3[precision + 2];
        // 每个三角形的角度
        float meshRadius = angle / precision;
        // 起始三角形朝向
        forward = Quaternion.AngleAxis(-angle / 2, Vector3.up) * forward;
        // 特殊设置0与1的顶点位置
        meshVectors[0] = originPos;
        meshVectors[1] = originPos + forward * radius;
        // 后续定点按规律生成
        for (int i = 2; i < precision + 2; i++)
        {
            // 旋转一个三角形的朝向
            forward = Quaternion.AngleAxis(meshRadius, Vector3.up) * forward;
            // 设置定点
            meshVectors[i] = originPos + forward * radius;
        }
        return meshVectors;
    }
    

    生成Triangles

    /// <summary>
    /// 生成triangles
    /// </summary>
    /// <param name="precision">三角形数量</param>
    /// <returns>triangles</returns>
    private int[] GetTriangles(int precision)
    {
        // 每个三角形三个triangle
        int[] meshTriangles = new int[precision * 3];
        // 按规律生成
        for (int i = 0; i < precision; i++)
        {
            int id = i * 3;
            meshTriangles[id] = 0;
            meshTriangles[id + 1] = i + 1;
            meshTriangles[id + 2] = i + 2;
        }
        return meshTriangles;
    }
    

    利用OnDrawGizmos绘制三角形

    public float angle; // 角度
    public float radius; // 半径
    public int precision; // 三角形数量(越多约成圆,效率越低)
    public GameObject origin; // 原点GameObject(表示原点位置用)
    private void OnDrawGizmos()
    {
        Mesh mesh = new Mesh();
        mesh.vertices = GetVectors(precision, origin.transform.position, origin.transform.forward);
        mesh.triangles = GetTriangles(precision);
        // 生成normals
        mesh.RecalculateNormals();
        Gizmos.color = Color.red;
        // 画线框(Mesh会挡住线框的绘制)
        for (int i = 1; i < mesh.vertices.Length; i++)
        {
            Gizmos.DrawLine(mesh.vertices[0], mesh.vertices[i]);
            Gizmos.DrawLine(mesh.vertices[i], mesh.vertices[i - 1]);
        }
        // 画Mesh
        Gizmos.DrawMesh(mesh);
    }
    

    Shader绘制

    属性

    _Inner ("Inner Texture", 2D) = "white" {} // 内圈贴图
    _Outer ("Outer Texture", 2D) = "white" {} // 外圈贴图
    _Color ("Color", Color) = (1, 1, 1, 1)    // 颜色
    _Angle ("Angle", Range(0, 360)) = 60	  // 角度
    _OutLine ("Out Line", Range(0, 1)) = 0.1  // 外圈宽度
    

    核心剔除代码

    fixed4 frag(fragmentInput i) : SV_Target 
    {
    	// 距离超过半径则剔除
        float distance = pow(i.uv.x - 0.5, 2) + pow(i.uv.y - 0.5, 2);
        if (distance > 0.25f) {
            discard;
        }
    
        float x = i.uv.x;
        float y = i.uv.y;
        float deg2rad = 0.017453; // 角度转弧度
    
        if (_Angle > 180) {
            if(y > 0.5 && abs(0.5 - y) >= abs(0.5 - x) / tan((180 - _Angle / 2) * deg2rad)) {
            	discard;
            }
            else {
            if(y > 0.5 || abs(0.5 -y) < abs(0.5 - x) / tan(_Angle / 2 * deg2rad)) {
            	discard;
            }
        }
    	// 外圈显示比例
        float outDis = 0.25 * pow((1 - _OutLine), 2);
    
        if (distance > outDis) {
        	// 外圈绘制
        	return tex2D(_Outer, i.uv) * _Color;
        }
        else {
        	// 内圈绘制
        	return tex2D(_Inner, i.uv) * _Color;
        }
    }
    
    Shader "Unlit/SectorShader" 
    {
        Properties {
            _Inner ("Inner Texture", 2D) = "white" {}
            _Outer ("Outer Texture", 2D) = "white" {}
            _Color ("Color", Color) = (1, 1, 1, 1)
            _Angle ("Angle", Range(0, 360)) = 60
            _OutLine ("Out Line", Range(0, 1)) = 0.1
        }
    
        SubShader {
            Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
            Pass {
                ZWrite Off
                Blend SrcAlpha OneMinusSrcAlpha
                CGPROGRAM
     
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
    
                sampler2D _Inner;
                sampler2D _Outer;
                float4 _Color;
                float _Angle;
                float _OutLine;
     
                struct fragmentInput 
                {
                    float4 pos : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                fragmentInput vert (appdata_base v)
                {
                    fragmentInput o;
    
                    o.pos = UnityObjectToClipPos (v.vertex);
                    o.uv = v.texcoord.xy;
    
                    return o;
                }
     
                fixed4 frag(fragmentInput i) : SV_Target 
                {
                    float distance = pow(i.uv.x - 0.5, 2) + pow(i.uv.y - 0.5, 2);
                    if (distance > 0.25f)
                    {
                        discard;
                    }
                    
                    float x = i.uv.x;
                    float y = i.uv.y;
                    float deg2rad = 0.017453; // 角度转弧度
    
                    if (_Angle > 180)
                    {
                        if(y > 0.5 && abs(0.5 - y) >= abs(0.5 - x) / tan((180 - _Angle / 2) * deg2rad))
                        {
                            discard;
                        }
                    }
                    else
                    {
                        if(y > 0.5 || abs(0.5 -y) < abs(0.5 - x) / tan(_Angle / 2 * deg2rad))
                        {
                            discard;
                        }
                    }
                    
                    float outDis = 0.25 * pow((1 - _OutLine), 2);
                    
                    if (distance > outDis)
                    {
                        return tex2D(_Outer, i.uv) * _Color;
                    }
                    else
                    {
                        return tex2D(_Inner, i.uv) * _Color;
                    }
                }
                
                ENDCG
            }
        }  
        FallBack "Diffuse"
    }
    
  • 相关阅读:
    linux vsftp配置
    oracle 执行计划查看
    oracle更新语句merge和update
    windows server2008 kettle部署
    oracle-trasnlate函数
    oracle 报警日志详解
    修改oracle实例名orcl为demo
    2017.11.05
    2017.10.22
    2017.09.22
  • 原文地址:https://www.cnblogs.com/SHOR/p/11454342.html
Copyright © 2011-2022 走看看