diff --git a/Assets/Editor/Utilities/SpriteColliderGenerator.cs b/Assets/Editor/Utilities/SpriteColliderGenerator.cs new file mode 100644 index 00000000..1d483390 --- /dev/null +++ b/Assets/Editor/Utilities/SpriteColliderGenerator.cs @@ -0,0 +1,819 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace Editor.Utilities +{ + public class SpriteColliderGenerator : EditorWindow + { + private Vector2 scrollPosition; + + [Tooltip("List of GameObjects with SpriteRenderers to generate colliders for")] + private List selectedObjects = new List(); + + [Tooltip("Controls how much to simplify the collider shape (lower values create more complex colliders)")] + private float simplificationTolerance = 0.05f; + + [Tooltip("When enabled, removes any existing PolygonCollider2D components before adding new ones")] + private bool replaceExistingColliders = true; + + [Tooltip("When enabled, applies colliders to all child objects with SpriteRenderers")] + private bool applyToChildren = false; + + [Tooltip("When enabled, allows scaling the collider outward or inward from the sprite center")] + private bool offsetFromCenter = false; + + [Tooltip("Distance to offset the collider from the sprite outline (positive values expand, negative values contract)")] + private float offsetDistance = 0f; + + [Tooltip("When enabled, creates trigger colliders instead of solid colliders")] + private bool generateTriggerColliders = false; + + [Tooltip("Threshold for transparency detection (pixels with alpha below this value are considered transparent)")] + private int alphaCutoff = 128; // Used when generating colliders (0-255) + + [Tooltip("Controls the level of detail for the generated collider (affects vertex count)")] + private int detailLevel = 2; // 1 = low, 2 = medium, 3 = high + + [Tooltip("When enabled, shows a preview of the colliders in the scene view before generating them")] + private bool previewColliders = true; + + [Tooltip("Color used for previewing colliders in the scene view")] + private Color previewColor = new Color(0.2f, 1f, 0.3f, 0.5f); + + private List previewMeshes = new List(); + + [MenuItem("Tools/Sprite Collider Generator")] + public static void ShowWindow() + { + GetWindow("Sprite Collider Generator"); + } + + private void OnDisable() + { + // Clean up any preview meshes when window is closed + foreach (var mesh in previewMeshes) + { + if (mesh != null) + { + DestroyImmediate(mesh); + } + } + previewMeshes.Clear(); + } + + private void OnGUI() + { + EditorGUILayout.BeginVertical(); + + EditorGUILayout.LabelField("Sprite Collider Generator", EditorStyles.boldLabel); + EditorGUILayout.HelpBox("Select GameObjects with SpriteRenderers and generate accurate PolygonCollider2D components based on the sprite outlines.", MessageType.Info); + + EditorGUILayout.Space(); + + // Object selection section + EditorGUILayout.LabelField("Selected Objects", EditorStyles.boldLabel); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(new GUIContent("Add Selected GameObjects", "Add GameObjects currently selected in the scene or project to the list for processing."))) + { + AddSelectedGameObjects(); + } + EditorGUILayout.EndHorizontal(); + + scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(150)); + + for (int i = 0; i < selectedObjects.Count; i++) + { + EditorGUILayout.BeginHorizontal(); + + selectedObjects[i] = (GameObject)EditorGUILayout.ObjectField(selectedObjects[i], typeof(GameObject), true); + + if (GUILayout.Button("X", GUILayout.Width(20))) + { + selectedObjects.RemoveAt(i); + i--; + } + + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.EndScrollView(); + + if (GUILayout.Button(new GUIContent("Clear All", "Remove all objects from the selection list."))) + { + selectedObjects.Clear(); + } + + EditorGUILayout.Space(); + + // Collider generation options + EditorGUILayout.LabelField("Generation Options", EditorStyles.boldLabel); + + // Detail level for collider generation (affects vertex count) + string[] detailOptions = new string[] { "Low", "Medium", "High" }; + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(new GUIContent("Detail Level:", "Controls the level of detail for the generated collider (affects vertex count)."), GUILayout.Width(180)); + detailLevel = EditorGUILayout.Popup(detailLevel - 1, detailOptions) + 1; + EditorGUILayout.EndHorizontal(); + + // Simplification tolerance (how much to simplify the collider) + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(new GUIContent("Simplification Tolerance:", "Controls how much to simplify the collider shape (lower values create more complex colliders)."), GUILayout.Width(180)); + simplificationTolerance = EditorGUILayout.Slider(simplificationTolerance, 0.01f, 0.2f); + EditorGUILayout.EndHorizontal(); + + // Alpha cutoff for transparency + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(new GUIContent("Alpha Cutoff (0-255):", "Threshold for transparency detection (pixels with alpha below this value are considered transparent)."), GUILayout.Width(180)); + alphaCutoff = EditorGUILayout.IntSlider(alphaCutoff, 0, 255); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + // Additional options + replaceExistingColliders = EditorGUILayout.Toggle( + new GUIContent("Replace Existing Colliders", "When enabled, removes any existing PolygonCollider2D components before adding new ones."), + replaceExistingColliders); + + applyToChildren = EditorGUILayout.Toggle( + new GUIContent("Apply To Children", "When enabled, applies colliders to all child objects with SpriteRenderers."), + applyToChildren); + + generateTriggerColliders = EditorGUILayout.Toggle( + new GUIContent("Generate Trigger Colliders", "When enabled, creates trigger colliders instead of solid colliders."), + generateTriggerColliders); + + // Offset option + offsetFromCenter = EditorGUILayout.Toggle( + new GUIContent("Offset From Center", "When enabled, allows scaling the collider outward or inward from the sprite center."), + offsetFromCenter); + + if (offsetFromCenter) + { + EditorGUI.indentLevel++; + offsetDistance = EditorGUILayout.FloatField( + new GUIContent("Offset Distance", "Distance to offset the collider from the sprite outline (positive values expand, negative values contract)."), + offsetDistance); + EditorGUI.indentLevel--; + } + + // Preview option + previewColliders = EditorGUILayout.Toggle( + new GUIContent("Preview Colliders", "When enabled, shows a preview of the colliders in the scene view before generating them."), + previewColliders); + + if (previewColliders) + { + EditorGUI.indentLevel++; + previewColor = EditorGUILayout.ColorField( + new GUIContent("Preview Color", "Color used for previewing colliders in the scene view."), + previewColor); + + // Create a horizontal layout for the preview buttons + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(new GUIContent("Update Preview", "Refresh the preview display in the scene view."))) + { + GenerateColliderPreviews(); + } + if (GUILayout.Button(new GUIContent("Clear Preview", "Remove all preview colliders from the scene view."))) + { + ClearPreviews(); + } + EditorGUILayout.EndHorizontal(); + + EditorGUI.indentLevel--; + } + + EditorGUILayout.Space(); + + // Generate colliders button + GUI.enabled = selectedObjects.Count > 0; + + if (GUILayout.Button(new GUIContent("Generate Colliders", "Create polygon colliders for all selected sprites based on current settings."))) + { + GenerateColliders(); + } + + GUI.enabled = true; + + EditorGUILayout.EndVertical(); + + // Force the scene view to repaint if we're showing previews + if (previewColliders && Event.current.type == EventType.Repaint) + { + SceneView.RepaintAll(); + } + } + + private void AddSelectedGameObjects() + { + foreach (GameObject obj in Selection.gameObjects) + { + if (!selectedObjects.Contains(obj)) + { + // Only add if it has a SpriteRenderer or any of its children do + if (obj.GetComponent() != null || + (applyToChildren && obj.GetComponentInChildren() != null)) + { + selectedObjects.Add(obj); + } + } + } + } + + private void GenerateColliderPreviews() + { + // Clean up existing preview meshes + foreach (var mesh in previewMeshes) + { + if (mesh != null) + { + DestroyImmediate(mesh); + } + } + previewMeshes.Clear(); + + if (!previewColliders || selectedObjects.Count == 0) + return; + + foreach (var obj in selectedObjects) + { + if (obj == null) continue; + + var spriteRenderers = applyToChildren ? + obj.GetComponentsInChildren() : + new SpriteRenderer[] { obj.GetComponent() }; + + foreach (var renderer in spriteRenderers) + { + if (renderer == null || renderer.sprite == null) + continue; + + Sprite sprite = renderer.sprite; + List paths = GetSpritePaths(sprite, simplificationTolerance); + if (paths.Count == 0) + continue; + + foreach (var path in paths) + { + // Create a preview mesh from the path + Mesh previewMesh = CreateMeshFromPath(path, renderer.transform); + if (previewMesh != null) + previewMeshes.Add(previewMesh); + } + } + } + } + + /// + /// Clears all preview meshes from the scene view + /// + private void ClearPreviews() + { + foreach (var mesh in previewMeshes) + { + if (mesh != null) + { + DestroyImmediate(mesh); + } + } + previewMeshes.Clear(); + + // Force a repaint of the scene view + SceneView.RepaintAll(); + } + + private Mesh CreateMeshFromPath(Vector2[] path, Transform transform) + { + if (path.Length < 3) + return null; + + Mesh mesh = new Mesh(); + + // Convert the path to 3D vertices and apply the sprite's transform + Vector3[] vertices = new Vector3[path.Length]; + for (int i = 0; i < path.Length; i++) + { + // Convert the local position to world space using the transform + vertices[i] = transform.TransformPoint(new Vector3(path[i].x, path[i].y, 0)); + } + + // Triangulate the polygon + Triangulator triangulator = new Triangulator(path); + int[] triangles = triangulator.Triangulate(); + + mesh.vertices = vertices; + mesh.triangles = triangles; + mesh.RecalculateNormals(); + + return mesh; + } + + private void GenerateColliders() + { + int successCount = 0; + List errors = new List(); + + Undo.RecordObjects(selectedObjects.ToArray(), "Generate Sprite Colliders"); + + foreach (var obj in selectedObjects) + { + if (obj == null) continue; + + try + { + var spriteRenderers = applyToChildren ? + obj.GetComponentsInChildren() : + new SpriteRenderer[] { obj.GetComponent() }; + + foreach (var renderer in spriteRenderers) + { + if (renderer == null || renderer.sprite == null) + continue; + + // Check if we're working with a prefab + bool isPrefab = PrefabUtility.IsPartOfPrefabAsset(renderer.gameObject); + GameObject targetObject = renderer.gameObject; + + if (isPrefab) + { + // If it's a prefab, we need special handling + string prefabPath = AssetDatabase.GetAssetPath(targetObject); + targetObject = PrefabUtility.LoadPrefabContents(prefabPath); + SpriteRenderer prefabRenderer = targetObject.GetComponent(); + + if (prefabRenderer == null || prefabRenderer.sprite == null) + { + PrefabUtility.UnloadPrefabContents(targetObject); + continue; + } + + if (GenerateColliderForRenderer(prefabRenderer)) + { + // Save the changes to the prefab + PrefabUtility.SaveAsPrefabAsset(targetObject, prefabPath); + successCount++; + } + + PrefabUtility.UnloadPrefabContents(targetObject); + } + else + { + // For scene objects, just generate the collider directly + if (GenerateColliderForRenderer(renderer)) + { + successCount++; + } + } + } + } + catch (Exception e) + { + errors.Add($"{obj.name}: {e.Message}"); + } + } + + // Clean up any preview meshes as we've now generated real colliders + ClearPreviews(); + + if (successCount > 0) + { + Debug.Log($"Successfully generated colliders for {successCount} sprite(s)."); + } + + if (errors.Count > 0) + { + Debug.LogError($"Errors occurred while generating colliders:\n{string.Join("\n", errors)}"); + } + } + + private bool GenerateColliderForRenderer(SpriteRenderer renderer) + { + if (renderer == null || renderer.sprite == null) + return false; + + Sprite sprite = renderer.sprite; + GameObject targetObject = renderer.gameObject; + + // Remove existing colliders if specified + if (replaceExistingColliders) + { + PolygonCollider2D[] existingColliders = targetObject.GetComponents(); + foreach (var collider in existingColliders) + { + Undo.DestroyObjectImmediate(collider); + } + } + + // Create a new polygon collider + PolygonCollider2D polygonCollider = Undo.AddComponent(targetObject); + if (polygonCollider == null) + return false; + + // Set as trigger if specified + polygonCollider.isTrigger = generateTriggerColliders; + + // Get paths from the sprite + List paths = GetSpritePaths(sprite, simplificationTolerance); + if (paths.Count == 0) + return false; + + // Apply offset if needed + if (offsetFromCenter && offsetDistance != 0) + { + for (int i = 0; i < paths.Count; i++) + { + Vector2[] offsetPath = new Vector2[paths[i].Length]; + for (int j = 0; j < paths[i].Length; j++) + { + // Calculate direction from center (0,0) to the point + Vector2 dir = paths[i][j].normalized; + // Apply offset in that direction + offsetPath[j] = paths[i][j] + dir * offsetDistance; + } + paths[i] = offsetPath; + } + } + + // Set the paths on the collider + polygonCollider.pathCount = paths.Count; + for (int i = 0; i < paths.Count; i++) + { + polygonCollider.SetPath(i, paths[i]); + } + + return true; + } + + private List GetSpritePaths(Sprite sprite, float tolerance) + { + List result = new List(); + + if (sprite == null) + return result; + + // Get the raw physics shape data from the sprite + int physicsShapeCount = sprite.GetPhysicsShapeCount(); + if (physicsShapeCount == 0) + { + // Use the sprite's bounds if no physics shape is defined + Vector2[] boundingBoxPath = new Vector2[4]; + Bounds bounds = sprite.bounds; + boundingBoxPath[0] = new Vector2(bounds.min.x, bounds.min.y); + boundingBoxPath[1] = new Vector2(bounds.min.x, bounds.max.y); + boundingBoxPath[2] = new Vector2(bounds.max.x, bounds.max.y); + boundingBoxPath[3] = new Vector2(bounds.max.x, bounds.min.y); + result.Add(boundingBoxPath); + return result; + } + + // Adjust the detail level based on the setting + float actualTolerance = tolerance; + switch (detailLevel) + { + case 1: // Low + actualTolerance = tolerance * 2.0f; + break; + case 2: // Medium - default + actualTolerance = tolerance; + break; + case 3: // High + actualTolerance = tolerance * 0.5f; + break; + } + + // Get all physics shapes from the sprite + for (int i = 0; i < physicsShapeCount; i++) + { + List path = new List(); + sprite.GetPhysicsShape(i, path); + + // Apply simplification if needed + if (actualTolerance > 0.01f) + { + path = SimplifyPath(path, actualTolerance); + } + + if (path.Count >= 3) // Need at least 3 points for a valid polygon + { + result.Add(path.ToArray()); + } + } + + return result; + } + + private List SimplifyPath(List points, float tolerance) + { + if (points.Count <= 3) + return points; + + // Implementation of Ramer-Douglas-Peucker algorithm for simplifying a polygon + List result = new List(); + List markers = new List(new int[points.Count]); + markers[0] = 1; + markers[points.Count - 1] = 1; + + SimplifyDouglasPeucker(points, tolerance, markers, 0, points.Count - 1); + + for (int i = 0; i < points.Count; i++) + { + if (markers[i] == 1) + { + result.Add(points[i]); + } + } + + return result; + } + + private void SimplifyDouglasPeucker(List points, float tolerance, List markers, int start, int end) + { + if (end <= start + 1) + return; + + float maxDistance = 0; + int maxIndex = start; + + Vector2 startPoint = points[start]; + Vector2 endPoint = points[end]; + + // Find the point furthest from the line segment + for (int i = start + 1; i < end; i++) + { + float distance = PerpendicularDistance(points[i], startPoint, endPoint); + if (distance > maxDistance) + { + maxDistance = distance; + maxIndex = i; + } + } + + // If the furthest point is beyond tolerance, mark it for keeping and recurse + if (maxDistance > tolerance) + { + markers[maxIndex] = 1; + SimplifyDouglasPeucker(points, tolerance, markers, start, maxIndex); + SimplifyDouglasPeucker(points, tolerance, markers, maxIndex, end); + } + } + + private float PerpendicularDistance(Vector2 point, Vector2 lineStart, Vector2 lineEnd) + { + if (lineStart == lineEnd) + return Vector2.Distance(point, lineStart); + + float dx = lineEnd.x - lineStart.x; + float dy = lineEnd.y - lineStart.y; + + // Normalize + float norm = Mathf.Sqrt(dx * dx + dy * dy); + if (norm < float.Epsilon) + return Vector2.Distance(point, lineStart); + + dx /= norm; + dy /= norm; + + // Calculate perpendicular distance + float px = point.x - lineStart.x; + float py = point.y - lineStart.y; + + float projectionLength = px * dx + py * dy; + + Vector2 projection = new Vector2( + lineStart.x + projectionLength * dx, + lineStart.y + projectionLength * dy); + + return Vector2.Distance(point, projection); + } + + // Scene view event handling for previewing colliders + [InitializeOnLoadMethod] + static void Initialize() + { + SceneView.duringSceneGui += OnSceneGUI; + } + + static void OnSceneGUI(SceneView sceneView) + { + // Find all open collider generator windows + var windows = Resources.FindObjectsOfTypeAll(); + foreach (var window in windows) + { + window.DrawColliderPreviews(sceneView); + } + } + + void DrawColliderPreviews(SceneView sceneView) + { + if (!previewColliders || previewMeshes.Count == 0) + return; + + // Draw all preview meshes with the selected color + Material previewMaterial = new Material(Shader.Find("Hidden/Internal-Colored")); + previewMaterial.SetPass(0); + previewMaterial.SetColor("_Color", previewColor); + + if (Event.current.type == EventType.Repaint) + { + GL.PushMatrix(); + GL.MultMatrix(Matrix4x4.identity); + + // Enable blending for transparency + GL.Begin(GL.TRIANGLES); + GL.Color(previewColor); + + foreach (var mesh in previewMeshes) + { + if (mesh != null) + { + // Draw each triangle in the mesh + for (int i = 0; i < mesh.triangles.Length; i += 3) + { + Vector3 v0 = mesh.vertices[mesh.triangles[i]]; + Vector3 v1 = mesh.vertices[mesh.triangles[i + 1]]; + Vector3 v2 = mesh.vertices[mesh.triangles[i + 2]]; + + GL.Vertex(v0); + GL.Vertex(v1); + GL.Vertex(v2); + } + } + } + + GL.End(); + GL.PopMatrix(); + + // Also draw the outline + GL.PushMatrix(); + GL.MultMatrix(Matrix4x4.identity); + GL.Begin(GL.LINES); + + // Set a more visible outline color + Color outlineColor = new Color(previewColor.r, previewColor.g, previewColor.b, 1f); + GL.Color(outlineColor); + + foreach (var mesh in previewMeshes) + { + if (mesh != null) + { + // Create a dictionary to track which edges we've drawn + HashSet drawnEdges = new HashSet(); + + // Draw edges of each triangle + for (int i = 0; i < mesh.triangles.Length; i += 3) + { + DrawEdgeIfNotDrawn(mesh.vertices[mesh.triangles[i]], mesh.vertices[mesh.triangles[i + 1]], drawnEdges); + DrawEdgeIfNotDrawn(mesh.vertices[mesh.triangles[i + 1]], mesh.vertices[mesh.triangles[i + 2]], drawnEdges); + DrawEdgeIfNotDrawn(mesh.vertices[mesh.triangles[i + 2]], mesh.vertices[mesh.triangles[i]], drawnEdges); + } + } + } + + GL.End(); + GL.PopMatrix(); + } + } + + private void DrawEdgeIfNotDrawn(Vector3 v1, Vector3 v2, HashSet drawnEdges) + { + // Create a unique key for this edge (order vertices to ensure uniqueness) + string edgeKey; + if (v1.x < v2.x || (v1.x == v2.x && v1.y < v2.y)) + edgeKey = $"{v1.x},{v1.y},{v1.z}_{v2.x},{v2.y},{v2.z}"; + else + edgeKey = $"{v2.x},{v2.y},{v2.z}_{v1.x},{v1.y},{v1.z}"; + + // Only draw if we haven't drawn this edge yet + if (!drawnEdges.Contains(edgeKey)) + { + GL.Vertex(v1); + GL.Vertex(v2); + drawnEdges.Add(edgeKey); + } + } + } + + // Helper class for triangulating polygons + public class Triangulator + { + private List m_points; + + public Triangulator(Vector2[] points) + { + m_points = new List(points); + } + + public int[] Triangulate() + { + List indices = new List(); + + int n = m_points.Count; + if (n < 3) + return indices.ToArray(); + + int[] V = new int[n]; + if (Area() > 0) + { + for (int v = 0; v < n; v++) + V[v] = v; + } + else + { + for (int v = 0; v < n; v++) + V[v] = (n - 1) - v; + } + + int nv = n; + int count = 2 * nv; + for (int v = nv - 1; nv > 2; ) + { + if ((count--) <= 0) + return indices.ToArray(); + + int u = v; + if (nv <= u) + u = 0; + v = u + 1; + if (nv <= v) + v = 0; + int w = v + 1; + if (nv <= w) + w = 0; + + if (Snip(u, v, w, nv, V)) + { + int a, b, c, s, t; + a = V[u]; + b = V[v]; + c = V[w]; + indices.Add(a); + indices.Add(b); + indices.Add(c); + + for (s = v, t = v + 1; t < nv; s++, t++) + V[s] = V[t]; + nv--; + count = 2 * nv; + } + } + + indices.Reverse(); + return indices.ToArray(); + } + + private float Area() + { + int n = m_points.Count; + float A = 0.0f; + for (int p = n - 1, q = 0; q < n; p = q++) + { + Vector2 pval = m_points[p]; + Vector2 qval = m_points[q]; + A += pval.x * qval.y - qval.x * pval.y; + } + return (A * 0.5f); + } + + private bool Snip(int u, int v, int w, int n, int[] V) + { + int p; + Vector2 A = m_points[V[u]]; + Vector2 B = m_points[V[v]]; + Vector2 C = m_points[V[w]]; + if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x)))) + return false; + for (p = 0; p < n; p++) + { + if ((p == u) || (p == v) || (p == w)) + continue; + Vector2 P = m_points[V[p]]; + if (InsideTriangle(A, B, C, P)) + return false; + } + return true; + } + + private bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P) + { + float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; + float cCROSSap, bCROSScp, aCROSSbp; + + ax = C.x - B.x; ay = C.y - B.y; + bx = A.x - C.x; by = A.y - C.y; + cx = B.x - A.x; cy = B.y - A.y; + apx = P.x - A.x; apy = P.y - A.y; + bpx = P.x - B.x; bpy = P.y - B.y; + cpx = P.x - C.x; cpy = P.y - C.y; + + aCROSSbp = ax * bpy - ay * bpx; + cCROSSap = cx * apy - cy * apx; + bCROSScp = bx * cpy - by * cpx; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); + } + } +} diff --git a/Assets/Editor/Utilities/SpriteColliderGenerator.cs.meta b/Assets/Editor/Utilities/SpriteColliderGenerator.cs.meta new file mode 100644 index 00000000..9aeb88d3 --- /dev/null +++ b/Assets/Editor/Utilities/SpriteColliderGenerator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 420526c0ea5943bb930e3e0913b9dee7 +timeCreated: 1758028488 \ No newline at end of file diff --git a/Assets/Prefabs/Minigames/DivingForPictures/Tile1.prefab b/Assets/Prefabs/Minigames/DivingForPictures/Tile1.prefab index 0c86ad5c..c2fe9982 100644 --- a/Assets/Prefabs/Minigames/DivingForPictures/Tile1.prefab +++ b/Assets/Prefabs/Minigames/DivingForPictures/Tile1.prefab @@ -10,6 +10,7 @@ GameObject: m_Component: - component: {fileID: 7111145574660306503} - component: {fileID: 3889795708575321074} + - component: {fileID: 7249681423942450184} m_Layer: 0 m_Name: Left_Tile2_0 m_TagString: Untagged @@ -87,6 +88,63 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!60 &7249681423942450184 +PolygonCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 864595161669782950} + m_Enabled: 1 + serializedVersion: 3 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_CompositeOperation: 0 + m_CompositeOrder: 0 + m_Offset: {x: 0, y: 0} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0.5, y: 0.5} + oldSize: {x: 2.37, y: 5} + newSize: {x: 2.37, y: 5} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + m_Points: + m_Paths: + - - {x: 0.575, y: -1.5} + - {x: 0.185, y: -0.63} + - {x: 1.145, y: 0.85999995} + - {x: 1.185, y: 1.41} + - {x: 0.835, y: 1.8499999} + - {x: 0.635, y: 2.5} + - {x: -1.185, y: 2.5} + - {x: -1.185, y: -2.5} + - {x: 0.635, y: -2.5} + - {x: 0.625, y: -1.64} + m_UseDelaunayMesh: 0 --- !u!1 &2171518497100337372 GameObject: m_ObjectHideFlags: 0 @@ -97,6 +155,7 @@ GameObject: m_Component: - component: {fileID: 1003080013996268193} - component: {fileID: 4856205316150460481} + - component: {fileID: 2843103852598642252} m_Layer: 0 m_Name: Right_Tile1_0 m_TagString: Untagged @@ -174,6 +233,69 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!60 &2843103852598642252 +PolygonCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2171518497100337372} + m_Enabled: 1 + serializedVersion: 3 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_CompositeOperation: 0 + m_CompositeOrder: 0 + m_Offset: {x: 0, y: 0} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0.5, y: 0.5} + oldSize: {x: 2.65, y: 5} + newSize: {x: 2.65, y: 5} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + m_Points: + m_Paths: + - - {x: -0.48499998, y: 2.5} + - {x: -0.49499997, y: 2.19} + - {x: 0.035, y: 1.66} + - {x: 0.035, y: 1.42} + - {x: -0.24499999, y: 1.15} + - {x: -0.285, y: 0.90999997} + - {x: -0.13499999, y: 0.45999998} + - {x: -1.115, y: -0.03} + - {x: -1.3249999, y: -0.35} + - {x: -1.2049999, y: -0.84999996} + - {x: -0.36499998, y: -1.0699999} + - {x: -0.585, y: -1.27} + - {x: -0.625, y: -1.65} + - {x: -0.48499998, y: -2.5} + - {x: 1.3249999, y: -2.5} + - {x: 1.3249999, y: 2.5} + m_UseDelaunayMesh: 0 --- !u!1 &2956826569642009690 GameObject: m_ObjectHideFlags: 0