unity通过Mesh箭头动态生成和更改长度

using System;
using System.Collections.Generic;
using UnityEngine;

public class ArrowGenerator : MonoBehaviour
{
    #region 配置参数
    //[Tooltip("箭头材质")]
    //public Material arrowMaterial;
    //[Tooltip("箭身材质")]
    //public Material bodyMaterial;
    [Range(0, 1)]
    [Tooltip("箭头占比")]
    public float headRatio;
    [Tooltip("箭头宽度")]
    public float width;
    public float length
    {
        set
        {
            if (Mathf.Abs(_length - value) > shake)
            {
                _length = value;
                MeshUpdata();
            }
        }
    }
    [Tooltip("箭头厚度")]
    public float high;
    [Tooltip("节点距离")]
    public float nodeDistance;
    [Tooltip("箭头弯曲趋势")]
    public AnimationCurve curve;
    [Tooltip("长度更新抖动误差")]
    public float shake;
    #endregion

    #region 私有参数
    private MeshFilter arrow;
    private float _length;
    private Mesh mesh;
    private float left;
    private float right;
    private float highHalf;
    private float curveLength;
    private float curveOrigin;
    private float _paragraphScale;

    /// 
    /// 箭身段落大小
    /// 
    private float paragraphScale
    {
        set
        {
            _paragraphScale = value;
            paragraphs = (int)Math.Ceiling((double)value);
        }
        get
        {
            return _paragraphScale;
        }
    }

    /// 
    /// 箭身段落数
    /// 
    private int paragraphs;
    private List vertexs;
    #endregion

    private void Awake()
    {
        arrow = GetComponent();
    }

    void Start()
    {
        _length = 10f;
        vertexs = new List();
        MeshCreate();
    }


    private void MeshCreate()
    {
        mesh = new Mesh();
        mesh.subMeshCount = 2;

        left = -width / 2;
        right = width / 2;
        highHalf = high / 2;

        float bodyLength = _length * (1 - headRatio);

        paragraphScale = bodyLength / nodeDistance;

        curveLength = curve[curve.length - 1].time - curve[0].time;
        curveOrigin = curve[0].value;

        Debug.Log(curveLength);
        Debug.Log(curve.Evaluate(curveLength) - curveOrigin);
        for (int i = 0; i <= paragraphs; i++)
        {
            float z;

            if (i == paragraphs && paragraphScale != (int)paragraphScale)
            {
                z = nodeDistance * (i - 1) + nodeDistance * (paragraphScale - (int)paragraphScale);
            }
            else
            {
                z = i * nodeDistance;
            }


            vertexs.Add(new Vector3(right, highHalf, z));
            vertexs.Add(new Vector3(left, highHalf, z));
            vertexs.Add(new Vector3(right, -highHalf, z));
            vertexs.Add(new Vector3(left, -highHalf, z));

            if (i == paragraphs)
            {
                //ArrowVertexsCreate(vertexs);
            }
        }

        mesh.vertices = vertexs.ToArray();//VertexBending(vertexs);
        mesh.SetIndices(BodyIndexCreate(paragraphs), MeshTopology.Triangles, 0);
        mesh.SetIndices(ArrowIndexCreate(vertexs.Count), MeshTopology.Triangles, 1);
        mesh.MarkDynamic();
        mesh.RecalculateNormals();
        arrow.mesh = mesh;
    }

    /// 
    /// 箭头顶点生成
    /// 
    /// 顶点数组
    public void ArrowVertexsCreate(List vertexs)
    {
        float headLength = _length * headRatio;
        float z = _length - headLength;
        float headWidth = width;
        vertexs.Add(new Vector3(headWidth, highHalf, z));
        vertexs.Add(new Vector3(-headWidth, highHalf, z));
        vertexs.Add(new Vector3(headWidth, -highHalf, z));
        vertexs.Add(new Vector3(-headWidth, -highHalf, z));
        vertexs.Add(new Vector3(0, 0, _length));
    }

    /// 
    /// 箭头索引生成
    /// 
    /// 顶点数组长度
    /// 索引数组
    public int[] ArrowIndexCreate(int vertexsLength)
    {
        int subOrigin = vertexsLength - 5;
        int[] index = new int[] {
            subOrigin, subOrigin + 3, subOrigin + 1,
            subOrigin, subOrigin + 2, subOrigin + 3,
            subOrigin, subOrigin+1, subOrigin+4,
            subOrigin,subOrigin+4,subOrigin+2,
            subOrigin+1,subOrigin+3,subOrigin+4,
            subOrigin+3,subOrigin+2,subOrigin+4
        };

        return index;
    }

    /// 
    ///  箭身索引生成
    /// 
    /// 段落数
    /// 索引数组
    public int[] BodyIndexCreate(int paragraphs)
    {
        List index = new List();
        index.AddRange(new int[] { 1, 0, 2, 3, 1, 2 });
        for (int i = 0; i < paragraphs; i++)
        {
            index.AddRange(new int[] { 4 * i, 4 * i + 1, 4 * i + 4, 4 * i + 1, 4 * i + 5, 4 * i + 4 });
            index.AddRange(new int[] { 4 * i + 3, 4 * i + 2, 4 * i + 6, 4 * i + 7, 4 * i + 3, 4 * i + 6 });
            index.AddRange(new int[] { 4 * i + 2, 4 * i, 4 * i + 4, 4 * i + 2, 4 * i + 4, 4 * i + 6 });
            index.AddRange(new int[] { 4 * i + 3, 4 * i + 5, 4 * i + 1, 4 * i + 3, 4 * i + 7, 4 * i + 5 });
        }
        return index.ToArray();
    }

    /// 
    /// 顶点随曲线弯曲
    /// 
    /// 顶点数组
    public Vector3[] VertexBending(List vertexs)
    {
        List tempList = new List(vertexs);
        Vector3 temp;
        for (int i = 0; i < vertexs.Count; i++)
        {
            float curveScale = tempList[i].z / _length;
            float y = curve.Evaluate(curveScale * curveLength) - curveOrigin;
            temp = tempList[i];
            temp.y += y;
            tempList[i] = temp;
        }
        return tempList.ToArray();
    }

    public void MeshUpdata()
    {
        float bodyLength = _length * (1 - headRatio);
        float paragraphScale_New = bodyLength / nodeDistance;
        float add = paragraphScale_New - (int)paragraphScale;
        int paragraphs_New = default;
        int nodeIndex = vertexs.Count - 10;
        paragraphScale = paragraphScale_New;
        vertexs.RemoveRange(nodeIndex + 1, 9);

        if (add > 0)
        {
            paragraphs_New = (int)Math.Ceiling((double)add);
            for (int i = 1; i <= paragraphs_New; i++)
            {
                float z;

                if (i == paragraphs_New && paragraphScale_New != (int)paragraphScale_New)
                {
                    z = vertexs[nodeIndex].z + nodeDistance * (i - 1) + nodeDistance * (paragraphScale_New - (int)paragraphScale_New);
                }
                else
                {
                    z = vertexs[nodeIndex].z + i * nodeDistance;
                }

                vertexs.Add(new Vector3(right, highHalf, z));
                vertexs.Add(new Vector3(left, highHalf, z));
                vertexs.Add(new Vector3(right, -highHalf, z));
                vertexs.Add(new Vector3(left, -highHalf, z));

                if (i == paragraphs_New)
                {
                    //ArrowVertexsCreate(vertexs);
                }
            }
        }
        else if (add < 0)
        {
            paragraphs_New = (int)Math.Abs(Math.Ceiling(add));
            float deviation = Math.Abs(add) - (int)Math.Abs(add);
            for (int i = 1; i <= paragraphs_New; i++)
            {
                vertexs.RemoveRange(vertexs.Count - 4, 4);
            }
            if (deviation != 0)
            {
                float z;
                z = vertexs[vertexs.Count - 1].z + nodeDistance * (1 - deviation);
                vertexs.Add(new Vector3(right, highHalf, z));
                vertexs.Add(new Vector3(left, highHalf, z));
                vertexs.Add(new Vector3(right, -highHalf, z));
                vertexs.Add(new Vector3(left, -highHalf, z));
            }

            ArrowVertexsCreate(vertexs);
        }
        mesh.Clear();
        mesh.subMeshCount = 2;
        mesh.vertices = vertexs.ToArray(); //VertexBending(vertexs);
        mesh.SetIndices(BodyIndexCreate(paragraphs), MeshTopology.Triangles, 0);
        mesh.SetIndices(ArrowIndexCreate(vertexs.Count), MeshTopology.Triangles, 1);
        mesh.RecalculateNormals();
    }

}

你可能感兴趣的:(unity,c#)