暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

GeometryCollider.cs 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Unity.Collections;
  4. using UnityEngine;
  5. using UnityEngine.Experimental.U2D;
  6. using UnityEngine.U2D;
  7. #if UNITY_EDITOR
  8. using UnityEditor;
  9. #endif
  10. namespace SpriteShapeExtras
  11. {
  12. [ExecuteAlways]
  13. public class GeometryCollider : MonoBehaviour
  14. {
  15. [SerializeField]
  16. bool m_UpdateCollider = false;
  17. int m_HashCode = 0;
  18. void Start()
  19. {
  20. }
  21. // Update is called once per frame
  22. void Update()
  23. {
  24. if (m_UpdateCollider)
  25. Bake(gameObject, false);
  26. }
  27. static public void Bake(GameObject go, bool forced)
  28. {
  29. var spriteShapeController = go.GetComponent<SpriteShapeController>();
  30. var spriteShapeRenderer = go.GetComponent<SpriteShapeRenderer>();
  31. var polyCollider = go.GetComponent<PolygonCollider2D>();
  32. var geometryCollider = go.GetComponent<GeometryCollider>();
  33. if (spriteShapeController != null && polyCollider != null)
  34. {
  35. var spline = spriteShapeController.spline;
  36. if (geometryCollider != null)
  37. {
  38. int splineHashCode = spline.GetHashCode();
  39. if (splineHashCode == geometryCollider.m_HashCode && !forced)
  40. return;
  41. geometryCollider.m_HashCode = splineHashCode;
  42. }
  43. NativeArray<ushort> indexArray;
  44. NativeSlice<Vector3> posArray;
  45. NativeSlice<Vector2> uv0Array;
  46. NativeArray<SpriteShapeSegment> geomArray;
  47. spriteShapeRenderer.GetChannels(65536, out indexArray, out posArray, out uv0Array);
  48. geomArray = spriteShapeRenderer.GetSegments(spline.GetPointCount() * 8);
  49. NativeArray<ushort> indexArrayLocal = new NativeArray<ushort>(indexArray.Length, Allocator.Temp);
  50. List<Vector2> points = new List<Vector2>();
  51. int indexCount = 0, vertexCount = 0, counter = 0;
  52. for (int u = 0; u < geomArray.Length; ++u)
  53. {
  54. if (geomArray[u].indexCount > 0)
  55. {
  56. for (int i = 0; i < geomArray[u].indexCount; ++i)
  57. {
  58. indexArrayLocal[counter] = (ushort)(indexArray[counter] + vertexCount);
  59. counter++;
  60. }
  61. vertexCount += geomArray[u].vertexCount;
  62. indexCount += geomArray[u].indexCount;
  63. }
  64. }
  65. Debug.Log(go.name + " : " + counter);
  66. OuterEdges(polyCollider, indexArrayLocal, posArray, indexCount);
  67. }
  68. }
  69. // Generate the outer edges from the Renderer mesh. Based on code from www.h3xed.com
  70. static void OuterEdges(PolygonCollider2D polygonCollider, NativeArray<ushort> triangles, NativeSlice<Vector3> vertices, int triangleCount)
  71. {
  72. // Get just the outer edges from the mesh's triangles (ignore or remove any shared edges)
  73. Dictionary<string, KeyValuePair<int, int>> edges = new Dictionary<string, KeyValuePair<int, int>>();
  74. for (int i = 0; i < triangleCount; i += 3)
  75. {
  76. for (int e = 0; e < 3; e++)
  77. {
  78. int vert1 = triangles[i + e];
  79. int vert2 = triangles[i + e + 1 > i + 2 ? i : i + e + 1];
  80. string edge = Mathf.Min(vert1, vert2) + ":" + Mathf.Max(vert1, vert2);
  81. if (edges.ContainsKey(edge))
  82. {
  83. edges.Remove(edge);
  84. }
  85. else
  86. {
  87. edges.Add(edge, new KeyValuePair<int, int>(vert1, vert2));
  88. }
  89. }
  90. }
  91. // Create edge lookup (Key is first vertex, Value is second vertex, of each edge)
  92. Dictionary<int, int> lookup = new Dictionary<int, int>();
  93. foreach (KeyValuePair<int, int> edge in edges.Values)
  94. {
  95. if (lookup.ContainsKey(edge.Key) == false)
  96. {
  97. lookup.Add(edge.Key, edge.Value);
  98. }
  99. }
  100. // Create empty polygon collider
  101. polygonCollider.pathCount = 0;
  102. // Loop through edge vertices in order
  103. int startVert = 0;
  104. int nextVert = startVert;
  105. int highestVert = startVert;
  106. List<Vector2> colliderPath = new List<Vector2>();
  107. while (true)
  108. {
  109. // Add vertex to collider path
  110. colliderPath.Add(vertices[nextVert]);
  111. // Get next vertex
  112. nextVert = lookup[nextVert];
  113. // Store highest vertex (to know what shape to move to next)
  114. if (nextVert > highestVert)
  115. {
  116. highestVert = nextVert;
  117. }
  118. // Shape complete
  119. if (nextVert == startVert)
  120. {
  121. // Add path to polygon collider
  122. polygonCollider.pathCount++;
  123. polygonCollider.SetPath(polygonCollider.pathCount - 1, colliderPath.ToArray());
  124. colliderPath.Clear();
  125. // Go to next shape if one exists
  126. if (lookup.ContainsKey(highestVert + 1))
  127. {
  128. // Set starting and next vertices
  129. startVert = highestVert + 1;
  130. nextVert = startVert;
  131. // Continue to next loop
  132. continue;
  133. }
  134. // No more verts
  135. break;
  136. }
  137. }
  138. }
  139. #if UNITY_EDITOR
  140. [MenuItem("SpriteShape/Generate Geometry Collider", false, 358)]
  141. public static void BakeGeometryCollider()
  142. {
  143. if (Selection.activeGameObject != null)
  144. GeometryCollider.Bake(Selection.activeGameObject, true);
  145. }
  146. #endif
  147. }
  148. }