/// <summary> /// Get the parameter container from tileData if tileData contains a tile with parameters or Null in other case /// </summary> static public ParameterContainer GetParamsFromTileData(Tileset tileset, uint tileData) { int brushId = Tileset.GetBrushIdFromTileData(tileData); TilesetBrush brush = tileset.FindBrush(brushId); if (brush) { return(brush.Params); } else { int tileId = Tileset.GetTileIdFromTileData(tileData); Tile tile = tileset.GetTile(tileId); if (tile != null) { return(tile.paramContainer); } } return(null); }
public static void DoGUIDrawTileFromTileData(Rect dstRect, uint tileData, Tileset tileset, Rect customUV = default(Rect)) { if (Event.current.type == EventType.Repaint) { int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = tileset.GetTile(tileId); if (tileId != Tileset.k_TileId_Empty && tileset.AtlasTexture) { if ((tileData & Tileset.k_TileFlag_FlipV) != 0) { GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), dstRect.center); } if ((tileData & Tileset.k_TileFlag_FlipH) != 0) { GUIUtility.ScaleAroundPivot(new Vector2(-1f, 1f), dstRect.center); } if ((tileData & Tileset.k_TileFlag_Rot90) != 0) { GUIUtility.RotateAroundPivot(90f, dstRect.center); } if (tile != null && tile.prefabData.prefab && tile.prefabData.showPrefabPreviewInTilePalette) { Texture2D assetPreview = AssetPreview.GetAssetPreview(tile.prefabData.prefab); if (assetPreview) { GUI.DrawTexture(dstRect, assetPreview, ScaleMode.ScaleToFit); } else { GUI.DrawTextureWithTexCoords(dstRect, tileset.AtlasTexture, customUV == default(Rect) && tile != null ? tile.uv : customUV, true); } } else { GUI.DrawTextureWithTexCoords(dstRect, tileset.AtlasTexture, customUV == default(Rect) && tile != null ? tile.uv : customUV, true); } GUI.matrix = Matrix4x4.identity; } } }
public bool AutotileWith(Tileset tileset, int selfBrushId, uint otherTileData) { int otherBrushId = (int)((uint)(otherTileData & Tileset.k_TileDataMask_BrushId) >> 16); if (otherBrushId != Tileset.k_BrushId_Default && otherBrushId != selfBrushId && (AutotilingMode & eAutotilingMode.SkipOtherBrushes) != 0) { return(false); } if ((AutotilingMode & eAutotilingMode.EmptyCells) != 0 && otherTileData == Tileset.k_TileData_Empty) { return(true); } if ((AutotilingMode & eAutotilingMode.Group) != 0) { Tile tile = tileset.GetTile((int)(otherTileData & Tileset.k_TileDataMask_TileId)); if (tile != null && Tileset.GetGroupAutotiling(Group, tile.autilingGroup)) { return(true); } } return(AutotileWith(selfBrushId, otherBrushId)); }
/// <summary> /// Returns a sprite for the tileId in the tileset and using the pixelsPerUnit specified (or the tileset pixels per units if the values is <= 0) /// </summary> public static Sprite GetOrCreateTileSprite(Tileset tileset, int tileId, float pixelsPerUnit = 0) { Sprite sprite = null; if (pixelsPerUnit <= 0) { pixelsPerUnit = tileset.PixelsPerUnit; } Tile tile = tileset.GetTile(tileId); if (tile != null) { Vector2 atlasSize = new Vector2(tileset.AtlasTexture.width, tileset.AtlasTexture.height); Rect spriteUV = new Rect(Vector2.Scale(tile.uv.position, atlasSize), Vector2.Scale(tile.uv.size, atlasSize)); string spriteName = tileset.name + "_" + tileId + "_" + pixelsPerUnit; if (!s_spriteCache.TryGetValue(spriteName, out sprite) || !sprite) { sprite = Sprite.Create(tileset.AtlasTexture, spriteUV, new Vector2(.5f, .5f), pixelsPerUnit); sprite.name = spriteName; s_spriteCache[spriteName] = sprite; } } return(sprite); }
private void DisplayCollider() { Event e = Event.current; if (Tileset.SelectedBrushId != Tileset.k_BrushId_Default) { EditorGUILayout.LabelField("Brush tile editing not allowed", EditorStyles.boldLabel); return; } bool isMultiselection = Tileset.TileSelection != null; bool saveChanges = false; Tile selectedTile = isMultiselection ? Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[0] & Tileset.k_TileDataMask_TileId)] : Tileset.SelectedTile; if (e.type == EventType.MouseDown) { m_isDragging = true; if (selectedTile.collData.vertices != null) { m_savedVertexData = new Vector2[selectedTile.collData.vertices.Length]; selectedTile.collData.vertices.CopyTo(m_savedVertexData, 0); } } else if (e.type == EventType.MouseUp) { m_isDragging = false; } Tileset.BackgroundColor = EditorGUILayout.ColorField(Tileset.BackgroundColor); if (m_prevBgColor != Tileset.BackgroundColor || Styles.Instance.colliderBgStyle.normal.background == null) { m_prevBgColor = Tileset.BackgroundColor; if (Styles.Instance.colliderBgStyle.normal.background == null) { Styles.Instance.colliderBgStyle.normal.background = new Texture2D(1, 1) { hideFlags = HideFlags.DontSave } } ; Styles.Instance.colliderBgStyle.normal.background.SetPixel(0, 0, Tileset.BackgroundColor); Styles.Instance.colliderBgStyle.normal.background.Apply(); } float aspectRatio = Tileset.TilePxSize.x / Tileset.TilePxSize.y; float padding = 2; // pixel size of the border around the tile //Rect rCollArea = GUILayoutUtility.GetRect(1, 1, GUILayout.Width(EditorGUIUtility.currentViewWidth), GUILayout.Height(EditorGUIUtility.currentViewWidth / aspectRatio)); Rect rCollArea = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); GUI.BeginGroup(rCollArea, Styles.Instance.colliderBgStyle); if (e.type == EventType.Repaint) { float pixelSize = rCollArea.width / (Tileset.TilePxSize.x + 2 * padding); m_mousePos = e.mousePosition; m_rTile = new Rect(padding * pixelSize, padding * pixelSize, rCollArea.width - 2 * padding * pixelSize, (rCollArea.width / aspectRatio) - 2 * padding * pixelSize); m_rTile.height = Mathf.Min(m_rTile.height, rCollArea.height - 2 * padding * pixelSize); m_rTile.width = (m_rTile.height * aspectRatio); } GUI.color = new Color(1f, 1f, 1f, 0.1f); GUI.DrawTexture(m_rTile, EditorGUIUtility.whiteTexture); GUI.color = Color.white; if (isMultiselection) { foreach (uint tileData in Tileset.TileSelection.selectionData) { int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); if (tile != null) { GUI.color = new Color(1f, 1f, 1f, 1f / Tileset.TileSelection.selectionData.Count); GUI.DrawTextureWithTexCoords(m_rTile, Tileset.AtlasTexture, tile.uv); } } GUI.color = Color.white; } else { GUI.DrawTextureWithTexCoords(m_rTile, Tileset.AtlasTexture, selectedTile.uv); } Color savedHandleColor = Handles.color; if (selectedTile.collData.type != eTileCollider.None) { Vector2[] collVertices = selectedTile.collData.type == eTileCollider.Full ? s_fullCollTileVertices : selectedTile.collData.vertices; if (collVertices == null || collVertices.Length == 0) { collVertices = selectedTile.collData.vertices = new Vector2[s_fullCollTileVertices.Length]; Array.Copy(s_fullCollTileVertices, collVertices, s_fullCollTileVertices.Length); EditorUtility.SetDirty(Tileset); } // Fix and snap positions for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = Mathf.Clamp01(Mathf.Round(s0.x * Tileset.TilePxSize.x) / Tileset.TilePxSize.x); s0.y = Mathf.Clamp01(Mathf.Round(s0.y * Tileset.TilePxSize.y) / Tileset.TilePxSize.y); collVertices[i] = s0; } // Draw edges Vector3[] polyEdges = new Vector3[collVertices.Length + 1]; for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = m_rTile.x + m_rTile.width * s0.x; s0.y = m_rTile.yMax - m_rTile.height * s0.y; Vector2 s1 = collVertices[(i + 1) % collVertices.Length]; s1.x = m_rTile.x + m_rTile.width * s1.x; s1.y = m_rTile.yMax - m_rTile.height * s1.y; polyEdges[i] = s0; polyEdges[i + 1] = s1; Handles.color = Color.green; Handles.DrawLine(s0, s1); //Draw normals { Handles.color = Color.white; Vector3 normPos = (s0 + s1) / 2f; Handles.DrawLine(normPos, normPos + Vector3.Cross(s1 - s0, Vector3.forward).normalized *m_rTile.yMin); } Handles.color = savedHandleColor; } float pixelSize = m_rTile.width / Tileset.TilePxSize.x; if (selectedTile.collData.type == eTileCollider.Polygon) { bool isAddingVertexOn = !m_isDragging && e.shift && m_activeVertexIdx == -1; bool isRemovingVertexOn = !m_isDragging && ((Application.platform == RuntimePlatform.OSXEditor)? e.command : e.control) && collVertices.Length > 3; if (isRemovingVertexOn && m_activeVertexIdx != -1 && e.type == EventType.MouseUp) { selectedTile.collData.vertices = new Vector2[collVertices.Length - 1]; for (int i = 0, j = 0; i < collVertices.Length; ++i) { if (i == m_activeVertexIdx) { continue; } selectedTile.collData.vertices[j] = collVertices[i]; ++j; } collVertices = selectedTile.collData.vertices; m_activeVertexIdx = -1; } float minDist = float.MaxValue; if (!m_isDragging) { m_activeVertexIdx = -1; } for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = m_rTile.x + m_rTile.width * s0.x; s0.y = m_rTile.yMax - m_rTile.height * s0.y; if (m_isDragging) { if (i == m_activeVertexIdx) { s0 = m_mousePos; s0 -= m_rTile.position; s0.x = Mathf.Clamp(Mathf.Round(s0.x / pixelSize) * pixelSize, 0, m_rTile.width); s0.y = Mathf.Clamp(Mathf.Round(s0.y / pixelSize) * pixelSize, 0, m_rTile.height); s0 += m_rTile.position; collVertices[i].x = Mathf.Clamp01((s0.x - m_rTile.x) / m_rTile.width); collVertices[i].y = Mathf.Clamp01((s0.y - m_rTile.yMax) / -m_rTile.height); } } else { float dist = Vector2.Distance(m_mousePos, s0); if (dist <= minDist && dist < Styles.Instance.collVertexHandleStyle.normal.background.width) { minDist = dist; m_activeVertexIdx = i; } } if (e.type == EventType.Repaint) { if (i == m_activeVertexIdx) { Styles.Instance.vertexCoordStyle.fontSize = (int)(Mathf.Min(10f, m_rTile.yMin / 2f)); GUI.Label(new Rect(0, 0, m_rTile.width, m_rTile.yMin), Vector2.Scale(collVertices[i], Tileset.TilePxSize).ToString(), Styles.Instance.vertexCoordStyle); } GUI.color = m_activeVertexIdx == i ? (isRemovingVertexOn ? Color.red : Color.cyan) : new Color(0.7f, 0.7f, 0.7f, 0.8f); Styles.Instance.collVertexHandleStyle.Draw(new Rect(s0.x - Styles.Instance.collVertexHandleStyle.normal.background.width / 2, s0.y - Styles.Instance.collVertexHandleStyle.normal.background.height / 2, 1, 1), i.ToString(), false, false, false, false); GUI.color = Color.white; } } if (isAddingVertexOn) { int segmentIdx; Vector2 newVertexPos = ClosestPointToPolyLine(polyEdges, out segmentIdx); if (e.type == EventType.MouseUp) { selectedTile.collData.vertices = new Vector2[collVertices.Length + 1]; segmentIdx = (segmentIdx + 1) % selectedTile.collData.vertices.Length; for (int i = 0, j = 0; i < selectedTile.collData.vertices.Length; ++i) { if (segmentIdx == i) { newVertexPos.x = Mathf.Clamp(Mathf.Round(newVertexPos.x / pixelSize) * pixelSize, m_rTile.x, m_rTile.xMax); newVertexPos.y = Mathf.Clamp(Mathf.Round(newVertexPos.y / pixelSize) * pixelSize, m_rTile.y, m_rTile.yMax); selectedTile.collData.vertices[i].x = Mathf.Clamp01((newVertexPos.x - m_rTile.x) / m_rTile.width); selectedTile.collData.vertices[i].y = Mathf.Clamp01((newVertexPos.y - m_rTile.yMax) / -m_rTile.height); } else { selectedTile.collData.vertices[i] = collVertices[j]; ++j; } } collVertices = selectedTile.collData.vertices; m_activeVertexIdx = -1; } else if (e.type == EventType.Repaint) { GUI.color = new Color(0.7f, 0.7f, 0.7f, 0.8f); Styles.Instance.collVertexHandleStyle.Draw(new Rect(newVertexPos.x - Styles.Instance.collVertexHandleStyle.normal.background.width / 2, newVertexPos.y - Styles.Instance.collVertexHandleStyle.normal.background.height / 2, 1, 1), segmentIdx.ToString(), false, false, false, false); GUI.color = Color.white; } } } if (e.type == EventType.MouseUp) { saveChanges = true; //remove duplicated vertex selectedTile.collData.vertices = selectedTile.collData.vertices.Distinct().ToArray(); if (selectedTile.collData.vertices.Length <= 2) { selectedTile.collData.vertices = m_savedVertexData; } //snap vertex positions selectedTile.collData.SnapVertices(Tileset); } } GUI.EndGroup(); if (GUILayout.Button("Reverse Normals")) { selectedTile.collData.vertices = selectedTile.collData.vertices.Reverse().ToArray(); } EditorGUILayout.Space(); string helpInfo = " - Click and drag over a vertex to move it" + "\n" + " - Hold Shift + Click for adding a new vertex" + "\n" + " - Hold " + ((Application.platform == RuntimePlatform.OSXEditor)? "Command" : "Ctrl") + " + Click for removing a vertex. (should be more than 3)" + "\n" + " - Check the normals for each edge. The normal is displayed in the collision side" + "\n" + ""; s_showHelp = EditorGUILayout.Foldout(s_showHelp, "Help"); if (s_showHelp) { EditorGUILayout.HelpBox(helpInfo, MessageType.Info); } //+++ Collider Settings float savedLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 40; if (isMultiselection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } EditorGUILayout.BeginHorizontal(GUILayout.MinWidth(140)); { EditorGUILayout.LabelField("Collider Data", EditorStyles.boldLabel); if (GUILayout.Button("Copy", GUILayout.Width(50))) { m_copiedColliderData = selectedTile.collData.Clone(); } if (GUILayout.Button("Paste", GUILayout.Width(50))) { selectedTile.collData = m_copiedColliderData.Clone(); saveChanges = true; } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUIUtility.labelWidth = 100; EditorGUI.BeginChangeCheck(); //selectedTile.collData.type = (eTileCollider)EditorGUILayout.EnumPopup("Collider Type", selectedTile.collData.type); EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel); EditorGUI.indentLevel += 2; string[] tileColliderNames = System.Enum.GetNames(typeof(eTileCollider)); selectedTile.collData.type = (eTileCollider)GUILayout.Toolbar((int)selectedTile.collData.type, tileColliderNames); EditorGUI.indentLevel -= 2; saveChanges |= EditorGUI.EndChangeCheck(); EditorGUIUtility.labelWidth = savedLabelWidth; //--- //Save changes if (saveChanges) { if (isMultiselection) { for (int i = 0; i < Tileset.TileSelection.selectionData.Count; ++i) { Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[i] & Tileset.k_TileDataMask_TileId)].collData = selectedTile.collData.Clone(); } } EditorUtility.SetDirty(Tileset); //Refresh selected tilemap Tilemap selectedTilemap = Selection.activeGameObject? Selection.activeGameObject.GetComponent <Tilemap>() : null; if (selectedTilemap) { selectedTilemap.Refresh(false, true); } } } /// <summary> // Get the point on a polyline (in 3D space) which is closest to the current // mouse position. And returns the segment index ( the vertex index of the segment with the closest point ) /// </summary> /// <param name="vertices"></param> /// <param name="closestSegmentIdx"></param> /// <returns></returns> Vector3 ClosestPointToPolyLine(Vector3[] vertices, out int closestSegmentIdx) { float minDist = float.MaxValue; closestSegmentIdx = 0; for (int i = 0; i < vertices.Length - 1; ++i) { float dist = HandleUtility.DistanceToLine(vertices[i], vertices[i + 1]); if (dist < minDist) { minDist = dist; closestSegmentIdx = i; } } return(HandleUtility.ClosestPointToPolyLine(vertices)); }
public void SetTileData(int locGridX, int locGridY, uint tileData) { if (locGridX >= 0 && locGridX < m_width && locGridY >= 0 && locGridY < m_height) { int tileIdx = locGridY * m_width + locGridX; int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); int prevTileId = (int)(m_tileDataList[tileIdx] & Tileset.k_TileDataMask_TileId); Tile prevTile = Tileset.GetTile(prevTileId); int brushId = Tileset.GetBrushIdFromTileData(tileData); int prevBrushId = Tileset.GetBrushIdFromTileData(m_tileDataList[tileIdx]); if (brushId != prevBrushId || brushId == 0) //NOTE: because of the autotiling mode, neighbour tiles could be affected by this change, even if the tile is not a brush { if (!s_currUpdatedTilechunk) // avoid this is chunks is being Updated from FillMeshData { // Refresh Neighbors ( and itself if needed ) for (int yf = -1; yf <= 1; ++yf) { for (int xf = -1; xf <= 1; ++xf) { if ((xf | yf) == 0) { if (brushId > 0) { // Refresh itself tileData = (tileData & ~Tileset.k_TileFlag_Updated); } } else { int gx = (locGridX + xf); int gy = (locGridY + yf); int idx = gy * m_width + gx; bool isInsideChunk = (gx >= 0 && gx < m_width && gy >= 0 && gy < m_height); uint neighborTileData = isInsideChunk ? m_tileDataList[idx] : ParentTilemap.GetTileData(GridPosX + locGridX + xf, GridPosY + locGridY + yf); int neighborBrushId = (int)((neighborTileData & Tileset.k_TileDataMask_BrushId) >> 16); TilesetBrush neighborBrush = ParentTilemap.Tileset.FindBrush(neighborBrushId); if (neighborBrush != null && (neighborBrush.AutotileWith(ParentTilemap.Tileset, neighborBrushId, tileData) || neighborBrush.AutotileWith(ParentTilemap.Tileset, neighborBrushId, m_tileDataList[tileIdx]))) { neighborTileData = (neighborTileData & ~Tileset.k_TileFlag_Updated); // force a refresh if (isInsideChunk) { m_tileDataList[idx] = neighborTileData; } else { ParentTilemap.SetTileData(GridPosX + gx, GridPosY + gy, neighborTileData); } } } } } } } else if (brushId > 0) { // Refresh itself tileData = (tileData & ~Tileset.k_TileFlag_Updated); } m_needsRebuildMesh |= (m_tileDataList[tileIdx] != tileData) || (tileData & Tileset.k_TileDataMask_TileId) == Tileset.k_TileId_Empty; m_needsRebuildColliders |= m_needsRebuildMesh && ( (prevBrushId > 0) || (brushId > 0) || // there is a brush (a brush could change the collider data later) (tile != null && tile.collData.type != eTileCollider.None) || (prevTile != null && prevTile.collData.type != eTileCollider.None) // prev. or new tile has colliders ); if (ParentTilemap.ColliderType != eColliderType.None && m_needsRebuildColliders) { // Refresh Neighbors tilechunk colliders, to make the collider autotiling // Only if neighbor is outside this tilechunk for (int yf = -1; yf <= 1; ++yf) { for (int xf = -1; xf <= 1; ++xf) { if ((xf | yf) != 0) // skip this tile position xf = yf = 0 { int gx = (locGridX + xf); int gy = (locGridY + yf); bool isInsideChunk = (gx >= 0 && gx < m_width && gy >= 0 && gy < m_height); if (!isInsideChunk) { ParentTilemap.InvalidateChunkAt(GridPosX + gx, GridPosY + gy, false, true); } } } } } // Update tile data m_tileDataList[tileIdx] = tileData; if (!STETilemap.DisableTilePrefabCreation) { // Create tile Objects if (tile != null && tile.prefabData.prefab != null) { CreateTileObject(tileIdx, tile.prefabData); } else { DestroyTileObject(tileIdx); } } TilesetBrush brush = ParentTilemap.Tileset.FindBrush(brushId); if (brushId != prevBrushId) { TilesetBrush prevBrush = ParentTilemap.Tileset.FindBrush(prevBrushId); if (prevBrush != null) { prevBrush.OnErase(this, locGridX, locGridY, tileData, prevBrushId); } } if (brush != null) { tileData = brush.OnPaint(this, locGridX, locGridY, tileData); } } }
private void UpdateMeshVertexColor() { //Debug.Log( "[" + ParentTilemap.name + "] FillData -> " + name); if (!Tileset || !Tileset.AtlasTexture) { return; } int totalTiles = m_width * m_height; if (s_colors32 == null) { s_colors32 = new List <Color32>(totalTiles * 4); } else { s_colors32.Clear(); } for (int ty = 0, tileIdx = 0; ty < m_height; ++ty) { for (int tx = 0; tx < m_width; ++tx, ++tileIdx) { uint tileData = m_tileDataList[tileIdx]; if (tileData != Tileset.k_TileData_Empty) { int brushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); TilesetBrush tileBrush = null; if (brushId > 0) { tileBrush = Tileset.FindBrush(brushId); } uint[] subtileData = tileBrush != null?tileBrush.GetSubtiles(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData) : null; if (subtileData == null) { if (tile != null) { if (tile.prefabData.prefab == null || tile.prefabData.showTileWithPrefab || //hide the tiles with prefabs ( unless showTileWithPrefab is true ) tileBrush && tileBrush.IsAnimated()) // ( skip if it's an animated brush ) { if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; s_colors32.Add(tileColor32.c0); s_colors32.Add(tileColor32.c1); s_colors32.Add(tileColor32.c2); s_colors32.Add(tileColor32.c3); } } } } else { for (int i = 0; i < subtileData.Length; ++i) { //if (tileUV != default(Rect)) //NOTE: if this is uncommented, there won't be coherence with geometry ( 16 vertices per tiles with subtiles ). But it means also, the tile shouldn't be null. { if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; Color32 middleColor = new Color32( System.Convert.ToByte((tileColor32.c0.r + tileColor32.c1.r + tileColor32.c2.r + tileColor32.c3.r) >> 2), System.Convert.ToByte((tileColor32.c0.g + tileColor32.c1.g + tileColor32.c2.g + tileColor32.c3.g) >> 2), System.Convert.ToByte((tileColor32.c0.b + tileColor32.c1.b + tileColor32.c2.b + tileColor32.c3.b) >> 2), System.Convert.ToByte((tileColor32.c0.a + tileColor32.c1.a + tileColor32.c2.a + tileColor32.c3.a) >> 2) ); switch (i) { case 0: s_colors32.Add(tileColor32.c0); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c0, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c0, .5f)); s_colors32.Add(middleColor); break; case 1: s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c1, .5f)); s_colors32.Add(tileColor32.c1); s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c1, .5f)); break; case 2: s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c2, .5f)); s_colors32.Add(middleColor); s_colors32.Add(tileColor32.c2); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c2, .5f)); break; case 3: s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c3, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c3, .5f)); s_colors32.Add(tileColor32.c3); break; } } } } } } } } }
/* * private void DummyDeepProfilingFix() * { * // For some reason, in Unity 2017.3.1f1, the Deep Profiling crashes unless FillMeshData call any method, even a dummy method like this * // Other weird thing is, the crash doesn't happens if one case of the switch statement is commented * // FINALLY: the fix was to change the Switch for if-else statements. I keep this notes just in case to remember about this weird issue. * } */ /// <summary> /// Fill the mesh data and return false if all tiles are empty /// </summary> /// <returns></returns> private bool FillMeshData() { //Debug.Log( "[" + ParentTilemap.name + "] FillData -> " + name); //DummyDeepProfilingFix(); if (!Tileset || !Tileset.AtlasTexture) { return(false); } s_currUpdatedTilechunk = this; int totalTiles = m_width * m_height; if (s_vertices == null) { s_vertices = new List <Vector3>(totalTiles * 4); } else { s_vertices.Clear(); } if (s_triangles == null) { s_triangles = new List <int>(totalTiles * 6); } else { s_triangles.Clear(); } if (s_colors32 == null) { s_colors32 = new List <Color32>(totalTiles * 4); } else { s_colors32.Clear(); } if (m_uv == null) { m_uv = new List <Vector2>(totalTiles * 4); } else { m_uv.Clear(); } Vector2[] subTileOffset = new Vector2[] { new Vector2(0f, 0f), new Vector2(CellSize.x / 2f, 0f), new Vector2(0f, CellSize.y / 2f), new Vector2(CellSize.x / 2f, CellSize.y / 2f), }; Vector2 subTileSize = CellSize / 2f; m_animatedTiles.Clear(); bool isEmpty = true; for (int ty = 0, tileIdx = 0; ty < m_height; ++ty) { for (int tx = 0; tx < m_width; ++tx, ++tileIdx) { uint tileData = m_tileDataList[tileIdx]; if (tileData != Tileset.k_TileData_Empty) { int brushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); TilesetBrush tileBrush = null; if (tileId >= 0 && tile == null && brushId <= 0) { Debug.LogWarning(ParentTilemap.name + "\\" + name + ": TileId " + tileId + " not found! GridPos(" + (GridPosX + tx) + "," + (GridPosY + ty) + ") tilaData 0x" + tileData.ToString("X")); m_tileDataList[tileIdx] = Tileset.k_TileData_Empty; } if (brushId > 0) { tileBrush = Tileset.FindBrush(brushId); if (tileBrush == null) { Debug.LogWarning(ParentTilemap.name + "\\" + name + ": BrushId " + brushId + " not found! GridPos(" + (GridPosX + tx) + "," + (GridPosY + ty) + ") tilaData 0x" + tileData.ToString("X")); m_tileDataList[tileIdx] = tileData & ~Tileset.k_TileDataMask_BrushId; } if (tileBrush != null && (m_invalidateBrushes || (tileData & Tileset.k_TileFlag_Updated) == 0)) { tileData = tileBrush.Refresh(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData); //+++NOTE: this code add support for animated brushes inside a random brush // Collateral effects of supporting changing the brush id in Refresh: // - When the random brush select a tile data with another brush id, this tile won't be a random tile any more // - If the tilemap is refreshed several times, and at least a tile data contains another brush id, then all tiles will loose the brush id of the random brush if (BrushBehaviour.Instance.BrushTilemap == ParentTilemap) // avoid changing brushId when updating the BrushTilemap { tileData &= ~Tileset.k_TileDataMask_BrushId; tileData |= (uint)(brushId << 16); } int newBrushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); if (brushId != newBrushId) { brushId = newBrushId; tileBrush = Tileset.FindBrush(brushId); } //--- tileData |= Tileset.k_TileFlag_Updated; // set updated flag m_tileDataList[tileIdx] = tileData; // update tileData tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); tile = Tileset.GetTile(tileId); // update created objects if (tile != null && tile.prefabData.prefab != null) { CreateTileObject(tileIdx, tile.prefabData); } else { DestroyTileObject(tileIdx); } } } isEmpty = false; if (tileBrush != null && tileBrush.IsAnimated()) { m_animatedTiles.Add(new AnimTileData() { VertexIdx = s_vertices.Count, Brush = tileBrush, SubTileIdx = -1 }); } s_currUVVertex = s_vertices.Count; Rect tileUV; uint[] subtileData = tileBrush != null?tileBrush.GetSubtiles(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData) : null; if (subtileData == null) { if (tile != null) { if (tile.prefabData.prefab == null || tile.prefabData.showTileWithPrefab || //hide the tiles with prefabs ( unless showTileWithPrefab is true ) tileBrush && tileBrush.IsAnimated()) // ( skip if it's an animated brush ) { tileUV = tile.uv; _AddTileToMesh(tileUV, tx, ty, tileData, Vector2.zero, CellSize); if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; s_colors32.Add(tileColor32.c0); s_colors32.Add(tileColor32.c1); s_colors32.Add(tileColor32.c2); s_colors32.Add(tileColor32.c3); } } } } else { for (int i = 0; i < subtileData.Length; ++i) { uint subTileData = subtileData[i]; int subTileId = (int)(subTileData & Tileset.k_TileDataMask_TileId); Tile subTile = Tileset.GetTile(subTileId); tileUV = subTile != null ? subTile.uv : default(Rect); //if (tileUV != default(Rect)) //NOTE: if this is uncommented, there won't be coherence with geometry ( 16 vertices per tiles with subtiles ). But it means also, the tile shouldn't be null. { _AddTileToMesh(tileUV, tx, ty, subTileData, subTileOffset[i], subTileSize, i); if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; Color32 middleColor = new Color32( System.Convert.ToByte((tileColor32.c0.r + tileColor32.c1.r + tileColor32.c2.r + tileColor32.c3.r) >> 2), System.Convert.ToByte((tileColor32.c0.g + tileColor32.c1.g + tileColor32.c2.g + tileColor32.c3.g) >> 2), System.Convert.ToByte((tileColor32.c0.b + tileColor32.c1.b + tileColor32.c2.b + tileColor32.c3.b) >> 2), System.Convert.ToByte((tileColor32.c0.a + tileColor32.c1.a + tileColor32.c2.a + tileColor32.c3.a) >> 2) ); //switch(i) // FIX Deep Profiling crash in Unity 2017.3.1f1 see: DummyDeepProfilingFix notes { if (i == 0) { s_colors32.Add(tileColor32.c0); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c0, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c0, .5f)); s_colors32.Add(middleColor); } else if (i == 1) { s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c1, .5f)); s_colors32.Add(tileColor32.c1); s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c1, .5f)); } else if (i == 2) { s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c2, .5f)); s_colors32.Add(middleColor); s_colors32.Add(tileColor32.c2); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c2, .5f)); } else if (i == 3) { s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c3, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c3, .5f)); s_colors32.Add(tileColor32.c3); } } } } } } } } } //NOTE: the destruction of tileobjects needs to be done here to avoid a Undo/Redo bug. Check inside DestroyTileObject for more information. for (int i = 0; i < m_tileObjToBeRemoved.Count; ++i) { DestroyTileObject(m_tileObjToBeRemoved[i]); } m_tileObjToBeRemoved.Clear(); s_currUpdatedTilechunk = null; return(!isEmpty); }
private bool FillColliderMeshData() { //Debug.Log( "[" + ParentTilemap.name + "] FillColliderMeshData -> " + name); if (Tileset == null || ParentTilemap.ColliderType == eColliderType.None) { return(false); } System.Type collider2DType = ParentTilemap.Collider2DType == e2DColliderType.EdgeCollider2D ? typeof(EdgeCollider2D) : typeof(PolygonCollider2D); Component[] aColliders2D = null; if (ParentTilemap.ColliderType == eColliderType._3D) { int totalTiles = m_width * m_height; if (s_meshCollVertices == null) { s_meshCollVertices = new List <Vector3>(totalTiles * 4); s_meshCollTriangles = new List <int>(totalTiles * 6); } else { s_meshCollVertices.Clear(); s_meshCollTriangles.Clear(); } } else //if (ParentTilemap.ColliderType == eColliderType._2D) { m_has2DColliders = true; s_openEdges.Clear(); aColliders2D = GetComponents(collider2DType); } float halvedCollDepth = ParentTilemap.ColliderDepth / 2f; bool isEmpty = true; for (int ty = 0, tileIdx = 0; ty < m_height; ++ty) { for (int tx = 0; tx < m_width; ++tx, ++tileIdx) { uint tileData = m_tileDataList[tileIdx]; if (tileData != Tileset.k_TileData_Empty) { int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); if (tile != null) { #if ENABLE_MERGED_SUBTILE_COLLIDERS TilesetBrush brush = ParentTilemap.Tileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData)); Vector2[] subTileMergedColliderVertices = brush ? brush.GetMergedSubtileColliderVertices(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData) : null; #else Vector2[] subTileMergedColliderVertices = null; #endif bool hasMergedColliders = subTileMergedColliderVertices != null; TileColliderData tileCollData = tile.collData; if (tileCollData.type != eTileCollider.None || hasMergedColliders) { isEmpty = false; int neighborCollFlags = 0; // don't remove, even using neighborTileCollData, neighborTileCollData is not filled if tile is empty bool isSurroundedByFullColliders = true; for (int i = 0; i < s_neighborSegmentMinMax.Length; ++i) { s_neighborSegmentMinMax[i].x = float.MaxValue; s_neighborSegmentMinMax[i].y = float.MinValue; } System.Array.Clear(neighborTileCollData, 0, neighborTileCollData.Length); if (!hasMergedColliders) { if ((tileData & (Tileset.k_TileFlag_FlipH | Tileset.k_TileFlag_FlipV | Tileset.k_TileFlag_Rot90)) != 0) { tileCollData = tileCollData.Clone(); tileCollData.ApplyFlippingFlags(tileData); } for (int i = 0; i < 4; ++i) { uint neighborTileData; bool isTriggerOrPolygon = ParentTilemap.IsTrigger || ParentTilemap.ColliderType == eColliderType._2D && ParentTilemap.Collider2DType == e2DColliderType.PolygonCollider2D; switch (i) { case 0: // Up Tile neighborTileData = (tileIdx + m_width) < m_tileDataList.Count ? m_tileDataList[tileIdx + m_width] : isTriggerOrPolygon ? Tileset.k_TileData_Empty : ParentTilemap.GetTileData(GridPosX + tx, GridPosY + ty + 1); break; case 1: // Right Tile neighborTileData = (tileIdx + 1) % m_width != 0 ? //(tileIdx + 1) < m_tileDataList.Count ? m_tileDataList[tileIdx + 1] : isTriggerOrPolygon ? Tileset.k_TileData_Empty : ParentTilemap.GetTileData(GridPosX + tx + 1, GridPosY + ty); break; case 2: // Down Tile neighborTileData = tileIdx >= m_width ? m_tileDataList[tileIdx - m_width] : isTriggerOrPolygon ? Tileset.k_TileData_Empty : ParentTilemap.GetTileData(GridPosX + tx, GridPosY + ty - 1); break; case 3: // Left Tile neighborTileData = tileIdx % m_width != 0 ? //neighborTileId = tileIdx >= 1 ? m_tileDataList[tileIdx - 1] : isTriggerOrPolygon ? Tileset.k_TileData_Empty : ParentTilemap.GetTileData(GridPosX + tx - 1, GridPosY + ty); break; default: neighborTileData = Tileset.k_TileData_Empty; break; } int neighborTileId = (int)(neighborTileData & Tileset.k_TileDataMask_TileId); if (neighborTileId != Tileset.k_TileId_Empty) { Vector2 segmentMinMax; TileColliderData neighborTileCollider; neighborTileCollider = Tileset.Tiles[neighborTileId].collData; if ((neighborTileData & (Tileset.k_TileFlag_FlipH | Tileset.k_TileFlag_FlipV | Tileset.k_TileFlag_Rot90)) != 0) { neighborTileCollider = neighborTileCollider.Clone(); if ((neighborTileData & Tileset.k_TileFlag_FlipH) != 0) { neighborTileCollider.FlipH(); } if ((neighborTileData & Tileset.k_TileFlag_FlipV) != 0) { neighborTileCollider.FlipV(); } if ((neighborTileData & Tileset.k_TileFlag_Rot90) != 0) { neighborTileCollider.Rot90(); } } neighborTileCollData[i] = neighborTileCollider; isSurroundedByFullColliders &= (neighborTileCollider.type == eTileCollider.Full); if (neighborTileCollider.type == eTileCollider.None) { segmentMinMax = new Vector2(float.MaxValue, float.MinValue); //NOTE: x will be min, y will be max } else if (neighborTileCollider.type == eTileCollider.Full) { segmentMinMax = new Vector2(0f, 1f); //NOTE: x will be min, y will be max neighborCollFlags |= (1 << i); } else { segmentMinMax = new Vector2(float.MaxValue, float.MinValue); //NOTE: x will be min, y will be max neighborCollFlags |= (1 << i); for (int j = 0; j < neighborTileCollider.vertices.Length; ++j) { Vector2 v = neighborTileCollider.vertices[j]; { if (i == 0 && v.y == 0 || i == 2 && v.y == 1) //Top || Bottom { if (v.x < segmentMinMax.x) { segmentMinMax.x = v.x; } if (v.x > segmentMinMax.y) { segmentMinMax.y = v.x; } } else if (i == 1 && v.x == 0 || i == 3 && v.x == 1) //Right || Left { if (v.y < segmentMinMax.x) { segmentMinMax.x = v.y; } if (v.y > segmentMinMax.y) { segmentMinMax.y = v.y; } } } } } s_neighborSegmentMinMax[i] = segmentMinMax; } else { isSurroundedByFullColliders = false; } } } // Create Mesh Colliders if (isSurroundedByFullColliders && !hasMergedColliders) { //Debug.Log(" Surrounded! " + tileIdx); } else { float px0 = tx * CellSize.x; float py0 = ty * CellSize.y; Vector2[] collVertices = subTileMergedColliderVertices; if (!hasMergedColliders) { collVertices = tileCollData.type == eTileCollider.Full ? s_fullCollTileVertices : tileCollData.vertices; } for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; Vector2 s1 = collVertices[i == (collVertices.Length - 1) ? 0 : i + 1]; if (hasMergedColliders) { ++i; // add ++i; in this case to go 2 by 2 because the collVertices for merged colliders will have the segments in pairs } // full collider optimization if ((tileCollData.type == eTileCollider.Full) && ( (i == 0 && neighborTileCollData[3].type == eTileCollider.Full) || // left tile has collider (i == 1 && neighborTileCollData[0].type == eTileCollider.Full) || // top tile has collider (i == 2 && neighborTileCollData[1].type == eTileCollider.Full) || // right tile has collider (i == 3 && neighborTileCollData[2].type == eTileCollider.Full) // bottom tile has collider ) ) { continue; } // polygon collider optimization else // if( tileCollData.type == eTileCollider.Polygon ) Or Full colliders if neighbor is not Full as well { Vector2 n, m; if (s0.y == 1f && s1.y == 1f) // top side { if ((neighborCollFlags & 0x1) != 0) // top tile has collider { n = s_neighborSegmentMinMax[0]; if (n.x < n.y && n.x <= s0.x && n.y >= s1.x) { continue; } } } else if (s0.x == 1f && s1.x == 1f) // right side { if ((neighborCollFlags & 0x2) != 0) // right tile has collider { n = s_neighborSegmentMinMax[1]; if (n.x < n.y && n.x <= s1.y && n.y >= s0.y) { continue; } } } else if (s0.y == 0f && s1.y == 0f) // bottom side { if ((neighborCollFlags & 0x4) != 0) // bottom tile has collider { n = s_neighborSegmentMinMax[2]; if (n.x < n.y && n.x <= s1.x && n.y >= s0.x) { continue; } } } else if (s0.x == 0f && s1.x == 0f) // left side { if ((neighborCollFlags & 0x8) != 0) // left tile has collider { n = s_neighborSegmentMinMax[3]; if (n.x < n.y && n.x <= s0.y && n.y >= s1.y) { continue; } } } else if (s0.y == 1f && s1.x == 1f) // top - right diagonal { if ((neighborCollFlags & 0x1) != 0 && (neighborCollFlags & 0x2) != 0) { n = s_neighborSegmentMinMax[0]; m = s_neighborSegmentMinMax[1]; if ((n.x < n.y && n.x <= s0.x && n.y == 1f) && (m.x < m.y && m.x <= s1.y && m.y == 1f)) { continue; } } } else if (s0.x == 1f && s1.y == 0f) // right - bottom diagonal { if ((neighborCollFlags & 0x2) != 0 && (neighborCollFlags & 0x4) != 0) { n = s_neighborSegmentMinMax[1]; m = s_neighborSegmentMinMax[2]; if ((n.x < n.y && n.x == 0f && n.y >= s0.y) && (m.x < m.y && m.x <= s1.x && m.y == 1f)) { continue; } } } else if (s0.y == 0f && s1.x == 0f) // bottom - left diagonal { if ((neighborCollFlags & 0x4) != 0 && (neighborCollFlags & 0x8) != 0) { n = s_neighborSegmentMinMax[2]; m = s_neighborSegmentMinMax[3]; if ((n.x < n.y && n.x == 0f && n.y >= s0.x) && (m.x < m.y && m.x == 0f && m.y >= s1.y)) { continue; } } } else if (s0.x == 0f && s1.y == 1f) // left - top diagonal { if ((neighborCollFlags & 0x8) != 0 && (neighborCollFlags & 0x1) != 0) { n = s_neighborSegmentMinMax[3]; m = s_neighborSegmentMinMax[0]; if ((n.x < n.y && n.x <= s0.y && n.y == 1f) && (m.x < m.y && m.x == 0f && m.y >= s1.x)) { continue; } } } } // Update s0 and s1 to world positions s0.x = px0 + CellSize.x * s0.x; s0.y = py0 + CellSize.y * s0.y; s1.x = px0 + CellSize.x * s1.x; s1.y = py0 + CellSize.y * s1.y; if (ParentTilemap.ColliderType == eColliderType._3D) { int collVertexIdx = s_meshCollVertices.Count; s_meshCollVertices.Add(new Vector3(s0.x, s0.y, -halvedCollDepth)); s_meshCollVertices.Add(new Vector3(s0.x, s0.y, halvedCollDepth)); s_meshCollVertices.Add(new Vector3(s1.x, s1.y, halvedCollDepth)); s_meshCollVertices.Add(new Vector3(s1.x, s1.y, -halvedCollDepth)); s_meshCollTriangles.Add(collVertexIdx + 0); s_meshCollTriangles.Add(collVertexIdx + 1); s_meshCollTriangles.Add(collVertexIdx + 2); s_meshCollTriangles.Add(collVertexIdx + 2); s_meshCollTriangles.Add(collVertexIdx + 3); s_meshCollTriangles.Add(collVertexIdx + 0); } else //if( ParentTilemap.ColliderType == eColliderType._2D ) { int linkedSegments = 0; int segmentIdxToMerge = -1; for (int edgeIdx = s_openEdges.Count - 1; edgeIdx >= 0 && linkedSegments < 2; --edgeIdx) { LinkedList <Vector2> edgeSegments = s_openEdges[edgeIdx]; if (edgeSegments.First.Value == edgeSegments.Last.Value) { continue; //skip closed edges } if (edgeSegments.Last.Value == s0) { if (segmentIdxToMerge >= 0) { LinkedList <Vector2> segmentToMerge = s_openEdges[segmentIdxToMerge]; if (s0 == segmentToMerge.First.Value) { for (LinkedListNode <Vector2> node = segmentToMerge.First.Next; node != null; node = node.Next) { edgeSegments.AddLast(node.Value); } s_openEdges.RemoveAt(segmentIdxToMerge); } /* Cannot join head with head or tail with tail, it will change the segment normal * else * for (LinkedListNode<Vector2> node = segmentToMerge.Last.Previous; node != null; node = node.Previous) * edgeSegments.AddLast(node.Value);*/ } else { segmentIdxToMerge = edgeIdx; edgeSegments.AddLast(s1); } ++linkedSegments; } /* Cannot join head with head or tail with tail, it will change the segment normal * else if( edgeSegments.Last.Value == s1 ) * else if (edgeSegments.First.Value == s0)*/ else if (edgeSegments.First.Value == s1) { if (segmentIdxToMerge >= 0) { LinkedList <Vector2> segmentToMerge = s_openEdges[segmentIdxToMerge]; if (s1 == segmentToMerge.Last.Value) { for (LinkedListNode <Vector2> node = edgeSegments.First.Next; node != null; node = node.Next) { segmentToMerge.AddLast(node.Value); } s_openEdges.RemoveAt(edgeIdx); } /* Cannot join head with head or tail with tail, it will change the segment normal * else * for (LinkedListNode<Vector2> node = edgeSegments.First.Next; node != null; node = node.Next) * segmentToMerge.AddFirst(node.Value);*/ } else { segmentIdxToMerge = edgeIdx; edgeSegments.AddFirst(s0); } ++linkedSegments; } } if (linkedSegments == 0) { LinkedList <Vector2> newEdge = new LinkedList <Vector2>(); newEdge.AddFirst(s0); newEdge.AddLast(s1); s_openEdges.Add(newEdge); } } } } } } } } } if (ParentTilemap.ColliderType == eColliderType._2D) { //+++ Process Edges //(NOTE: this was added to fix issues related with lighting, otherwise leave this commented) { // Remove vertex inside a line RemoveRedundantVertices(s_openEdges); // Split segments (NOTE: This is not working with polygon colliders) /*/ commented unless necessary for performance reasons * if (ParentTilemap.Collider2DType == e2DColliderType.EdgeCollider2D) * { * openEdges = SplitSegments(openEdges); * } * //*/ } //--- //Create Edges for (int i = 0; i < s_openEdges.Count; ++i) { LinkedList <Vector2> edgeSegments = s_openEdges[i]; bool reuseCollider = i < aColliders2D.Length; Collider2D collider2D = reuseCollider ? (Collider2D)aColliders2D[i] : (Collider2D)gameObject.AddComponent(collider2DType); collider2D.enabled = true; collider2D.isTrigger = ParentTilemap.IsTrigger; collider2D.sharedMaterial = ParentTilemap.PhysicMaterial2D; if (ParentTilemap.Collider2DType == e2DColliderType.EdgeCollider2D) { ((EdgeCollider2D)collider2D).points = edgeSegments.ToArray(); } else { ((PolygonCollider2D)collider2D).SetPath(0, edgeSegments.ToArray()); } } //Destroy unused edge colliders for (int i = s_openEdges.Count; i < aColliders2D.Length; ++i) { if (!s_isOnValidate) { DestroyImmediate(aColliders2D[i]); } else { ((Collider2D)aColliders2D[i]).enabled = false; } } } return(!isEmpty); }