Last active
June 5, 2026 09:34
-
-
Save mattvr/8cdcc922d1a75d0a7a7abf5d46e23ef0 to your computer and use it in GitHub Desktop.
Curved plane for Unity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| [RequireComponent(typeof(MeshFilter))] | |
| [RequireComponent(typeof(MeshRenderer))] | |
| public class CurvedPlane : MonoBehaviour | |
| { | |
| private class MeshData | |
| { | |
| public Vector3[] Vertices { get; set; } | |
| public Vector2[] Uvs { get; set; } | |
| public int[] Triangles { get; set; } | |
| } | |
| [SerializeField] private float height = 1f; | |
| [SerializeField] private float radius = 2f; | |
| [SerializeField] [Range(1, 1024)] private int numSegments = 32; | |
| [SerializeField] [Range(0f, 360f)] private float curvatureDegrees = 60f; | |
| [SerializeField] private bool useArc = true; | |
| [SerializeField] private bool flipNormals = false; | |
| private MeshData plane; | |
| void Start() | |
| { | |
| Generate(); | |
| } | |
| void OnValidate() | |
| { | |
| Generate(); | |
| } | |
| [ContextMenu("Generate")] | |
| public void Generate() | |
| { | |
| GenerateScreen(); | |
| UpdateMeshFilter(); | |
| } | |
| private void UpdateMeshFilter() | |
| { | |
| var filter = GetComponent<MeshFilter>(); | |
| var mesh = new Mesh | |
| { | |
| vertices = plane.Vertices, | |
| uv = plane.Uvs, | |
| triangles = plane.Triangles | |
| }; | |
| mesh.RecalculateNormals(); | |
| mesh.RecalculateBounds(); | |
| filter.mesh = mesh; | |
| } | |
| private void GenerateScreen() | |
| { | |
| plane = new MeshData | |
| { | |
| Vertices = new Vector3[(numSegments + 2) * 2], | |
| Uvs = new Vector2[(numSegments + 2) * 2], | |
| Triangles = new int[numSegments * 6] | |
| }; | |
| int i, j; | |
| for (i = j = 0; i < numSegments + 1; i++) | |
| { | |
| GenerateVertexPair(ref i, ref j); | |
| if (i < numSegments) | |
| { | |
| GenerateLeftTriangle(ref i, ref j); | |
| GenerateRightTriangle(ref i, ref j); | |
| } | |
| } | |
| } | |
| private void GenerateVertexPair(ref int i, ref int j) | |
| { | |
| float amt = ((float)i) / numSegments; | |
| float arcDegrees = curvatureDegrees * Mathf.Deg2Rad; | |
| float theta = -0.5f + amt; | |
| var x = useArc ? Mathf.Sin(theta * arcDegrees) * radius : (-0.5f * radius) + (amt * radius); | |
| var z = Mathf.Cos(theta * arcDegrees) * radius; | |
| plane.Vertices[i] = new Vector3(x, height / 2f, z); | |
| plane.Vertices[i + numSegments + 1] = new Vector3(x, -height / 2f, z); | |
| plane.Uvs[i] = new Vector2(amt, 1f); | |
| plane.Uvs[i + numSegments + 1] = new Vector2(amt, 0f); | |
| } | |
| private void GenerateLeftTriangle(ref int i, ref int j) | |
| { | |
| plane.Triangles[j++] = i; | |
| plane.Triangles[j++] = flipNormals ? i + numSegments + 1 : i + 1; | |
| plane.Triangles[j++] = flipNormals ? i + 1 : i + numSegments + 1; | |
| } | |
| private void GenerateRightTriangle(ref int i, ref int j) | |
| { | |
| plane.Triangles[j++] = i + 1; | |
| plane.Triangles[j++] = flipNormals ? i + numSegments + 1 : i + numSegments + 2; | |
| plane.Triangles[j++] = flipNormals ? i + numSegments + 2 : i + numSegments + 1; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would suggest adding UVs to it.
You would just need to ad a uv array in the Mesh Data Set class, fill it like this after you set the vertices:
plane.UVs[i] = new Vector2(i / (float)numSegments, 1);
plane.UVs[i + numSegments + 1] = new Vector2(i / (float)numSegments, 0);
and then attach it to the mesh.