using System; using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.Splines; namespace SplineLevelCreator { [ExecuteInEditMode()] public class s_SplineRoad : MonoBehaviour { [SerializeField] MeshFilter meshFilter; [SerializeField] SplineSampler splineSampler; Spline spline; [SerializeField] private int resolution; [SerializeField] private float width; [SerializeField] private bool generateWall; [SerializeField] private float wallHeight; List vertsP1; List vertsP2; private float uvOffset; private List uvs; private void Awake() { if (splineSampler == null) { splineSampler = GetComponent(); Debug.Log(splineSampler); } if (meshFilter == null) { meshFilter = GetComponent(); Debug.Log(meshFilter); } if (splineSampler != null || meshFilter != null) { Rebuild(); } } private void OnEnable() { Spline.Changed += OnSplineChanged; GetVerts(); } private void OnDisable() { Spline.Changed -= OnSplineChanged; } private void OnValidate() { Rebuild(); } private void OnSplineChanged(Spline arg1, int arg2, SplineModification arg3) { Rebuild(); } private void Rebuild() { GetVerts(); BuildMesh(); } public void GetVerts() { vertsP1 = new List(); vertsP2 = new List(); float step = 1f / (float)resolution; Vector3 p1; Vector3 p2; for (int j = 0; j < splineSampler.NumSplines(); j++) { for (int i = 0; i < resolution; i++) { float t = step * i; splineSampler.SampleSplineWidth(j, t, width, out p1, out p2); vertsP1.Add(p1); vertsP2.Add(p2); } splineSampler.SampleSplineWidth(j, 1f, width, out p1, out p2); vertsP1.Add(p1); vertsP2.Add(p2); } } public void BuildMesh() { Mesh mesh = new Mesh(); List verts = new List(); // Store the vertices in a list List tris = new List(); // Store the triangles in a list int offset = 0; int length = vertsP2.Count; List uvs = new List(); // Initialize UVs list for the entire mesh for (int currentSplineIndex = 0; currentSplineIndex < splineSampler.NumSplines(); currentSplineIndex++) // For loop to iterate and build the mesh for each spline { int splineOffset = resolution * currentSplineIndex; // Offset for the current spline and amount of resolution splineOffset += currentSplineIndex; // Iterate and build the mesh for the current spline for (int currentSplinePoint = 1; currentSplinePoint < resolution + 1; currentSplinePoint++) { // Get the points for the current spline's quad int vertOffset = splineOffset + currentSplinePoint; Vector3 p1 = vertsP1[vertOffset - 1]; Vector3 p2 = vertsP2[vertOffset - 1]; Vector3 p3 = vertsP1[vertOffset]; Vector3 p4 = vertsP2[vertOffset]; offset = 4 * resolution * currentSplineIndex; offset += 4 * (currentSplinePoint - 1); // Assign the triangles for the current spline's quad int t1 = offset + 0; int t2 = offset + 2; int t3 = offset + 3; int t4 = offset + 3; int t5 = offset + 1; int t6 = offset + 0; // Add the vertices and triangles to the lists verts.AddRange(new List { p1, p2, p3, p4 }); tris.AddRange(new List { t1, t2, t3, t4, t5, t6 }); // Calculate the UVs for the current spline's quad float distance = Vector3.Distance(p1, p3) / 4f; float uvDistance = uvOffset + distance; uvs.AddRange(new List { new Vector2(uvOffset, 0), new Vector2(uvOffset, 1), new Vector2(uvDistance, 0), new Vector2(uvDistance, 1) }); } } // Assign the vertices and triangles to the mesh and update it mesh.SetVertices(verts); mesh.SetTriangles(tris, 0); // The UVs should now have the correct size for the entire mesh mesh.SetUVs(0, uvs); meshFilter.mesh = mesh; } // Draw the spline points private void OnDrawGizmos() { if (vertsP1 == null || vertsP2 == null) { return; } Gizmos.color = Color.red; for (int i = 0; i < vertsP1.Count; i++) { Gizmos.DrawSphere(vertsP1[i], 0.1f); } Gizmos.color = Color.blue; for (int i = 0; i < vertsP2.Count; i++) { Gizmos.DrawSphere(vertsP2[i], 0.1f); } // Draw the lines between the left and right points Gizmos.color = Color.white; for (int i = 0; i < vertsP1.Count; i++) { Gizmos.DrawLine(vertsP1[i], vertsP2[i]); } } } }