├── LICENSE ├── PolygonMesh2D.cs ├── README.md └── example.gif /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Tiger Oakes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PolygonMesh2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | 5 | [ExecuteInEditMode] 6 | [RequireComponent (typeof (PolygonCollider2D))] 7 | [RequireComponent (typeof (MeshRenderer))] 8 | [RequireComponent (typeof (MeshFilter))] 9 | /// 10 | /// Builds a Mesh for a gameObject using the PolygonCollider2D's path 11 | public class PolygonMesh2D : MonoBehaviour { 12 | protected PolygonCollider2D polygon; 13 | protected MeshFilter meshFilter; 14 | 15 | ///The index of the polygon path to use for the mesh 16 | int pathIndex = 0; 17 | ///The Z position for the generated mesh 18 | public float zPosition = 0f; 19 | 20 | void Start() { 21 | polygon = gameObject.GetComponent(); 22 | meshFilter = gameObject.GetComponent(); 23 | } 24 | 25 | #if UNITY_EDITOR 26 | /// 27 | ///(Re)builds the Mesh using the path of the PolygonCollider2D 28 | public void OnColliderUpdate() { 29 | Vector2[] path = polygon.GetPath(pathIndex); 30 | Mesh msh = new Mesh(); 31 | 32 | msh.vertices = path.Select(v => new Vector3(v.x, v.y, zPosition)).ToArray(); 33 | msh.triangles = new Triangulator(path).Triangulate(); 34 | 35 | msh.RecalculateNormals(); 36 | msh.RecalculateBounds(); 37 | meshFilter.mesh = msh; 38 | 39 | //recalculate UV 40 | Bounds bounds = msh.bounds; 41 | 42 | msh.uv = path.Select(v => new Vector2(v.x / bounds.size.x, v.y / bounds.size.y)).ToArray(); 43 | } 44 | 45 | void Update() { 46 | if (!Application.isPlaying) OnColliderUpdate(); 47 | } 48 | #endif 49 | } 50 | 51 | class Triangulator { 52 | private List mPoints = new List(); 53 | 54 | public Triangulator (Vector2[] points) { 55 | mPoints = new List(points); 56 | } 57 | 58 | public int[] Triangulate() { 59 | List indices = new List(); 60 | 61 | int n = mPoints.Count; 62 | if (n < 3) return indices.ToArray(); 63 | 64 | int[] V = new int[n]; 65 | if (Area() > 0) { 66 | for (int v = 0; v < n; v++) 67 | V[v] = v; 68 | } 69 | else { 70 | for (int v = 0; v < n; v++) 71 | V[v] = (n - 1) - v; 72 | } 73 | 74 | int nv = n; 75 | int count = 2 * nv; 76 | for (int m = 0, v = nv - 1; nv > 2; ) { 77 | if ((count--) <= 0) 78 | return indices.ToArray(); 79 | 80 | int u = v; 81 | if (nv <= u) 82 | u = 0; 83 | v = u + 1; 84 | if (nv <= v) 85 | v = 0; 86 | int w = v + 1; 87 | if (nv <= w) 88 | w = 0; 89 | 90 | if (Snip(u, v, w, nv, V)) { 91 | int a, b, c, s, t; 92 | a = V[u]; 93 | b = V[v]; 94 | c = V[w]; 95 | indices.Add(a); 96 | indices.Add(b); 97 | indices.Add(c); 98 | m++; 99 | for (s = v, t = v + 1; t < nv; s++, t++) 100 | V[s] = V[t]; 101 | nv--; 102 | count = 2 * nv; 103 | } 104 | } 105 | 106 | indices.Reverse(); 107 | return indices.ToArray(); 108 | } 109 | 110 | private float Area () { 111 | int n = mPoints.Count; 112 | float A = 0.0f; 113 | for (int p = n - 1, q = 0; q < n; p = q++) { 114 | Vector2 pval = mPoints[p]; 115 | Vector2 qval = mPoints[q]; 116 | A += pval.x * qval.y - qval.x * pval.y; 117 | } 118 | return (A * 0.5f); 119 | } 120 | 121 | private bool Snip (int u, int v, int w, int n, int[] V) { 122 | int p; 123 | Vector2 A = mPoints[V[u]]; 124 | Vector2 B = mPoints[V[v]]; 125 | Vector2 C = mPoints[V[w]]; 126 | if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x)))) 127 | return false; 128 | for (p = 0; p < n; p++) { 129 | if ((p == u) || (p == v) || (p == w)) 130 | continue; 131 | Vector2 P = mPoints[V[p]]; 132 | if (InsideTriangle(A, B, C, P)) 133 | return false; 134 | } 135 | return true; 136 | } 137 | 138 | private bool InsideTriangle (Vector2 A, Vector2 B, Vector2 C, Vector2 P) { 139 | float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; 140 | float cCROSSap, bCROSScp, aCROSSbp; 141 | 142 | ax = C.x - B.x; ay = C.y - B.y; 143 | bx = A.x - C.x; by = A.y - C.y; 144 | cx = B.x - A.x; cy = B.y - A.y; 145 | apx = P.x - A.x; apy = P.y - A.y; 146 | bpx = P.x - B.x; bpy = P.y - B.y; 147 | cpx = P.x - C.x; cpy = P.y - C.y; 148 | 149 | aCROSSbp = ax * bpy - ay * bpx; 150 | cCROSSap = cx * apy - cy * apx; 151 | bCROSScp = bx * cpy - by * cpx; 152 | 153 | return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Polygon2D Editor for Unity 4 | 5 | ![Example usage animation](example.gif) 6 | 7 | Uses the PolygonCollider2D collider to generate a mesh for a gameobject, 8 | letting you draw polygonal platforms in the Unity edtior via the Edit Collider button. 9 | Just drag the script onto your platform GameObject and you're good to go. 10 | 11 | This script uses the [Triangulator](http://wiki.unity3d.com/index.php?title=Triangulator) class. 12 | 13 | ## Installing / Getting started 14 | 15 | Just **[download the script](PolygonMesh2D.cs)** and place it somewhere inside your Unity project's assets. 16 | Everything needed in contained within one file. 17 | 18 | Use the component by dragging it onto a GameObject or by using the Add Component dialog. This will automatically add a Polygon Collider 2D component if it isn't already present. 19 | 20 | In the Polygon Collider 2D Component, click the "Edit Collider" button to adjust the shape of the collider. The mesh will autoatically adjust itself to fill the collider. 21 | 22 | ## Licensing 23 | 24 | Licsenced under the [MIT License](./LICENSE). 25 | -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NotWoods/unity-polygon-2d-editor/aa8ebd85e6a8eb22ddbb03b54b552688460ae9fc/example.gif --------------------------------------------------------------------------------