Preface
Through Bezier curve, we get many groups of curves. Now we need to draw a track on the curve.
thinking
The nodes on the curve are calculated by cross multiplication.
Cross multiplication of the first node and the next node
The middle node calculates the cross product of the previous node and the next node, and then does the mean processing
Cross multiply the last node with the previous node
The effect is as follows:

The core code is as follows:
public class LineMeshCreater : MonoBehaviour { public Mesh GetMesh(Vector3[] posarray, float width , Vector3 world, Vector3 nextNode = default) { Mesh mesh = new Mesh(); DrawMesh(mesh, posarray, width , world , nextNode); return mesh; } /// <summary> //Drawing Mesh /// </summary> /// <param name="mesh"></param> /// <param name="posarray"></param> /// <param name="width"></param> public void DrawMesh(Mesh mesh, Vector3[] posarray, float width, Vector3 world, Vector3 nextNode = default) { mesh.Clear(); mesh.vertices = getVertices(posarray, width , world , nextNode); mesh.triangles = getTriangles(mesh.vertexCount); mesh.RecalculateNormals(); } /// <summary> ///Vertex calculation /// </summary> /// <returns></returns> Vector3[] getVertices(Vector3[] posarray, float width , Vector3 world , Vector3 nextNode = default) { Vector3[] vector3s = new Vector3[posarray.Length * 2]; for (int i = 0; i < posarray.Length; i++) { Vector3 reght = Vector3.zero; if (i > 0 && i < posarray.Length - 1) { Vector3 t_l, t_r; t_l = t_r = Vector3.zero; //Cross product vector to the left of node getCross(posarray[i - 1] - posarray[i], world, ref t_l); //Cross product vector to the right of node getCross(posarray[i + 1] - posarray[i], world, ref t_r); //Mean value t_r = -t_r; reght = (t_r + t_l) / 2; } else if (i == posarray.Length - 1) { if (nextNode != Vector3.zero) { //Cross product vector to next node getCross(nextNode - posarray[i], world, ref reght); reght = -reght; } else { //Cross product vector to the left of node getCross(posarray[i - 1] - posarray[i], world, ref reght); } } else { //Cross product vector to the right of node getCross(posarray[i + 1] - posarray[i], world, ref reght); reght = -reght; } //Right vertex vector3s[i * 2] = reght * (width / 2) + posarray[i] - posarray[0]; //Left vertex vector3s[i * 2 + 1] = -reght * (width / 2) + posarray[i] - posarray[0]; //Debug.DrawLine(vector3s[i * 2] + posarray[0], vector3s[i * 2 + 1] + posarray[0], Color.red); } return vector3s; } /// <summary> /// fork multiplication /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="vector"></param> void getCross(Vector3 a, Vector3 b, ref Vector3 vector) { vector = new Vector3( a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x ).normalized; } /// <summary> ///Trigonometric calculation /// </summary> /// <param name="count"></param> /// <returns></returns> int[] getTriangles(int count) { List<int> vector3s = new List<int>(); for (int i = 0; i < count - 2; i += 2) { //Lower right triangle int p0, p1, p2; p0 = i; p1 = i + 1; p2 = i + 2; vector3s.Add(p0); vector3s.Add(p1); vector3s.Add(p2); //Upper left triangle p0 = i + 1; p1 = i + 3; p2 = i + 2; vector3s.Add(p0); vector3s.Add(p1); vector3s.Add(p2); } return vector3s.ToArray(); } }
In addition, it should be noted that the last node of each group of curve nodes and the second node of the next group need to be cross multiplied once, so that they can be perfectly spliced without gaps.
Setting a subdivision value in the Bezier curve can make the actual track smoother, with the following effects:
