Skip to content

Instantly share code, notes, and snippets.

@unitycoder
Created August 22, 2023 10:40
Show Gist options
  • Select an option

  • Save unitycoder/1428e745abd97a289f25bbc497bcf08c to your computer and use it in GitHub Desktop.

Select an option

Save unitycoder/1428e745abd97a289f25bbc497bcf08c to your computer and use it in GitHub Desktop.

Revisions

  1. unitycoder created this gist Aug 22, 2023.
    87 changes: 87 additions & 0 deletions ColliderCreator.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,87 @@
    // https://www.h3xed.com/programming/automatically-create-polygon-collider-2d-from-2d-mesh-in-unity
    using System.Collections.Generic;
    using UnityEngine;

    public class ColliderCreator : MonoBehaviour
    {
    void Start()
    {
    // Stop if no mesh filter exists or there's already a collider
    if (GetComponent<PolygonCollider2D>() || GetComponent<MeshFilter>() == null) {
    return;
    }

    // Get triangles and vertices from mesh
    int[] triangles = GetComponent<MeshFilter>().mesh.triangles;
    Vector3[] vertices = GetComponent<MeshFilter>().mesh.vertices;

    // Get just the outer edges from the mesh's triangles (ignore or remove any shared edges)
    Dictionary<string, KeyValuePair<int, int>> edges = new Dictionary<string, KeyValuePair<int, int>>();
    for (int i = 0; i < triangles.Length; i += 3) {
    for (int e = 0; e < 3; e++) {
    int vert1 = triangles[i + e];
    int vert2 = triangles[i + e + 1 > i + 2 ? i : i + e + 1];
    string edge = Mathf.Min(vert1, vert2) + ":" + Mathf.Max(vert1, vert2);
    if (edges.ContainsKey(edge)) {
    edges.Remove(edge);
    } else {
    edges.Add(edge, new KeyValuePair<int, int>(vert1, vert2));
    }
    }
    }

    // Create edge lookup (Key is first vertex, Value is second vertex, of each edge)
    Dictionary<int, int> lookup = new Dictionary<int, int>();
    foreach (KeyValuePair<int, int> edge in edges.Values) {
    if (lookup.ContainsKey(edge.Key) == false) {
    lookup.Add(edge.Key, edge.Value);
    }
    }

    // Create empty polygon collider
    PolygonCollider2D polygonCollider = gameObject.AddComponent<PolygonCollider2D>();
    polygonCollider.pathCount = 0;

    // Loop through edge vertices in order
    int startVert = 0;
    int nextVert = startVert;
    int highestVert = startVert;
    List<Vector2> colliderPath = new List<Vector2>();
    while (true) {

    // Add vertex to collider path
    colliderPath.Add(vertices[nextVert]);

    // Get next vertex
    nextVert = lookup[nextVert];

    // Store highest vertex (to know what shape to move to next)
    if (nextVert > highestVert) {
    highestVert = nextVert;
    }

    // Shape complete
    if (nextVert == startVert) {

    // Add path to polygon collider
    polygonCollider.pathCount++;
    polygonCollider.SetPath(polygonCollider.pathCount - 1, colliderPath.ToArray());
    colliderPath.Clear();

    // Go to next shape if one exists
    if (lookup.ContainsKey(highestVert + 1)) {

    // Set starting and next vertices
    startVert = highestVert + 1;
    nextVert = startVert;

    // Continue to next loop
    continue;
    }

    // No more verts
    break;
    }
    }
    }
    }