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();
}
}