using UnityEngine; using System.Collections.Generic; [ExecuteInEditMode] [AddComponentMenu("Destructible 2D/D2D Edge Colliders")] public class D2D_EdgeColliders : D2D_Collider { [System.Serializable] public class Cell { public List EdgeCollider2Ds = new List(); public void Destroy() { foreach (var edgeCollider2D in EdgeCollider2Ds) { D2D_Helper.Destroy(edgeCollider2D); } EdgeCollider2Ds.Clear(); } public void ReplaceColliders(List newEdgeCollider2Ds) { Destroy(); EdgeCollider2Ds.AddRange(newEdgeCollider2Ds); } public void UpdateColliderSettings(bool isTrigger, PhysicsMaterial2D material) { foreach (var edgeCollider2D in EdgeCollider2Ds) { if (edgeCollider2D != null) { edgeCollider2D.isTrigger = isTrigger; edgeCollider2D.sharedMaterial = material; } } } } [D2D_PopupAttribute(8, 16, 32, 64, 128, 256)] public int CellSize = 64; [D2D_RangeAttribute(0.0f, 0.3f)] public float Tolerance = 0.01f; [SerializeField] private List cells = new List(); [SerializeField] private int cellsX; [SerializeField] private int cellsY; [SerializeField] private int cellsXY; [SerializeField] private int width; [SerializeField] private int height; public void RebuildAllColliders(Texture2D alphaTex) { if (alphaTex != null) { RebuildColliders(alphaTex, 0, alphaTex.width, 0, alphaTex.height); } else { DestroyAllCells(); } } public void RebuildColliders(Texture2D alphaTex, int xMin, int xMax, int yMin, int yMax) { UpdateColliders(alphaTex); if (cells.Count > 0) { //var stopwatch = System.Diagnostics.Stopwatch.StartNew(); xMin = Mathf.Clamp(xMin - 1, 0, alphaTex.width - 1); yMin = Mathf.Clamp(yMin - 1, 0, alphaTex.height - 1); var cellXMin = xMin / CellSize; var cellYMin = yMin / CellSize; var cellXMax = (xMax + CellSize - 1) / CellSize; var cellYMax = (yMax + CellSize - 1) / CellSize; for (var cellY = cellYMin; cellY <= cellYMax; cellY++) { for (var cellX = cellXMin; cellX <= cellXMax; cellX++) { if (cellX >= 0 && cellX < cellsX && cellY >= 0 && cellY < cellsY) { xMin = CellSize * cellX; yMin = CellSize * cellY; xMax = Mathf.Min(CellSize + xMin, alphaTex.width); yMax = Mathf.Min(CellSize + yMin, alphaTex.height); var cell = cells[cellX + cellY * cellsX]; var newEdgeCollider2Ds = D2D_EdgeCalculator.Generate(gameObject, alphaTex, xMin, xMax, yMin, yMax, Tolerance); cell.ReplaceColliders(newEdgeCollider2Ds); cell.UpdateColliderSettings(IsTrigger, Material); } } } //stopwatch.Stop(); Debug.Log("RebuildColliders took " + stopwatch.ElapsedMilliseconds + " ms"); } } public override void UpdateColliderSettings() { foreach (var cell in cells) { if (cell != null) { cell.UpdateColliderSettings(IsTrigger, Material); } } } private void UpdateColliders(Texture2D alphaTex) { if (alphaTex != null && alphaTex.width > 0 && alphaTex.height > 0 && CellSize > 0 && Tolerance >= 0.0f) { cellsX = (alphaTex.width + CellSize - 1) / CellSize; cellsY = (alphaTex.height + CellSize - 1) / CellSize; cellsXY = cellsX * cellsY; if (cells.Count > 0) { if (cells.Count != cellsXY) { DestroyAllCells(); } if (alphaTex.width != width || alphaTex.height != height) { DestroyAllCells(); } } // Rebuild all cells? if (cells.Count == 0 && cellsXY > 0) { width = alphaTex.width; height = alphaTex.height; for (var i = 0; i < cellsXY; i++) { cells.Add(new Cell()); } } } else { DestroyAllCells(); } } protected virtual void OnDestroy() { D2D_Helper.DestroyManaged(DestroyAllCells); } protected override void RebuildAll() { var destructible = D2D_Helper.GetComponentUpwards(transform); if (destructible != null) { RebuildAllColliders(destructible.AlphaTex); } } private void DestroyAllCells() { if (cells.Count > 0) { foreach (var cell in cells) { cell.Destroy(); } cells.Clear(); } } #if UNITY_EDITOR protected override void SetHideFlags(HideFlags hideFlags) { foreach (var cell in cells) { foreach (var edgeCollider2D in cell.EdgeCollider2Ds) { if (edgeCollider2D != null) { edgeCollider2D.hideFlags = hideFlags; } } } } #else protected override void SetHideFlags(HideFlags hideFlags) { } #endif }