public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY) { // Build local mesh Vector3[] localMeshVertices = new Vector3[0]; int[] localMeshIndices = new int[0]; BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localMeshVertices, ref localMeshIndices); // only process when there are more than two triangles // avoids a lot of branches later if (localMeshIndices.Length > 6) { // Remove duplicate verts localMeshVertices = WeldVertices(localMeshVertices, ref localMeshIndices); // Remove duplicate and back-to-back faces // Removes inside faces localMeshIndices = RemoveDuplicateFaces(localMeshIndices); // Merge coplanar faces // Optimize (remove unused vertices, reindex) } #if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) foreach (EdgeCollider2D c2d in chunk.edgeColliders) { if (c2d != null) { tk2dUtil.DestroyImmediate(c2d); } } chunk.edgeColliders.Clear(); #endif if (localMeshVertices.Length > 0) { if (chunk.colliderMesh != null) { tk2dUtil.DestroyImmediate(chunk.colliderMesh); chunk.colliderMesh = null; } if (chunk.meshCollider == null) { chunk.meshCollider = chunk.gameObject.GetComponent<MeshCollider>(); if (chunk.meshCollider == null) chunk.meshCollider = tk2dUtil.AddComponent<MeshCollider>(chunk.gameObject); } chunk.colliderMesh = tk2dUtil.CreateMesh(); chunk.colliderMesh.vertices = localMeshVertices; chunk.colliderMesh.triangles = localMeshIndices; chunk.colliderMesh.RecalculateBounds(); chunk.meshCollider.sharedMesh = chunk.colliderMesh; } else { chunk.DestroyColliderData(tileMap); } }
private void CreateChunk(SpriteChunk chunk) { if ((chunk.spriteIds == null) || (chunk.spriteIds.Length == 0)) { chunk.spriteIds = new int[this.divX * this.divY]; for (int i = 0; i < (this.divX * this.divY); i++) { chunk.spriteIds[i] = -1; } } }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk) { // Build local mesh Vector3[] localMeshVertices = new Vector3[0]; int[] localMeshIndices = new int[0]; BuildLocalMeshForChunk(tileMap, chunk, ref localMeshVertices, ref localMeshIndices); // only process when there are more than two triangles // avoids a lot of branches later if (localMeshIndices.Length > 6) { // Remove duplicate verts localMeshVertices = WeldVertices(localMeshVertices, ref localMeshIndices); // Remove duplicate and back-to-back faces // Removes inside faces localMeshIndices = RemoveDuplicateFaces(localMeshIndices); // Merge coplanar faces // Optimize (remove unused vertices, reindex) } if (localMeshVertices.Length > 0) { if (chunk.colliderMesh != null) { GameObject.DestroyImmediate(chunk.colliderMesh); chunk.colliderMesh = null; } if (chunk.meshCollider == null) { chunk.meshCollider = chunk.gameObject.GetComponent<MeshCollider>(); if (chunk.meshCollider == null) chunk.meshCollider = chunk.gameObject.AddComponent<MeshCollider>(); } chunk.colliderMesh = tileMap.GetOrCreateMesh(); chunk.colliderMesh.vertices = localMeshVertices; chunk.colliderMesh.triangles = localMeshIndices; chunk.colliderMesh.RecalculateBounds(); if (tileMap.serializeRenderData) chunk.mesh.RecalculateNormals(); chunk.meshCollider.sharedMesh = chunk.colliderMesh; } else { chunk.DestroyColliderData(tileMap); } }
void CreateChunk(SpriteChunk chunk) { if (chunk.spriteIds == null || chunk.spriteIds.Length == 0) { chunk.spriteIds = new int[divX * divY]; for (int i = 0; i < divX * divY; ++i) chunk.spriteIds[i] = -1; } }
public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, int layer, int[] prefabCounts) { int[] spriteIds = chunk.spriteIds; GameObject[] tilePrefabs = tileMap.data.tilePrefabs; Vector3 tileSize = tileMap.data.tileSize; Transform parent = chunk.gameObject.transform; float x = 0f; float y = 0f; tileMap.data.GetTileOffset(out x, out y); for (int i = 0; i < tileMap.partitionSizeY; i++) { float num4 = ((baseY + i) & 1) * x; for (int j = 0; j < tileMap.partitionSizeX; j++) { int tileFromRawTile = GetTileFromRawTile(spriteIds[(i * tileMap.partitionSizeX) + j]); if ((tileFromRawTile >= 0) && (tileFromRawTile < tilePrefabs.Length)) { UnityEngine.Object original = tilePrefabs[tileFromRawTile]; if (original != null) { prefabCounts[tileFromRawTile]++; GameObject item = GetExistingTilePrefabInstance(tileMap, baseX + j, baseY + i, layer); bool flag = item != null; if (item == null) { item = UnityEngine.Object.Instantiate(original, Vector3.zero, Quaternion.identity) as GameObject; } if (item != null) { GameObject obj4 = original as GameObject; Vector3 vector2 = new Vector3(tileSize.x * (j + num4), tileSize.y * i, 0f); bool enablePrefabOffset = false; TileInfo tileInfoForSprite = tileMap.data.GetTileInfoForSprite(tileFromRawTile); if (tileInfoForSprite != null) { enablePrefabOffset = tileInfoForSprite.enablePrefabOffset; } if (enablePrefabOffset && (obj4 != null)) { vector2 += obj4.transform.position; } if (!flag) { item.name = original.name + " " + prefabCounts[tileFromRawTile].ToString(); } tk2dUtil.SetTransformParent(item.transform, parent); item.transform.localPosition = vector2; TilePrefabsX.Add(baseX + j); TilePrefabsY.Add(baseY + i); TilePrefabsLayer.Add(layer); TilePrefabsInstance.Add(item); } } } } } }
/* Creates Farseer Box Colliders for tiles in chunk and sets them as children of container. */ void GenerateCollidersForChunk(SpriteChunk chunk, GameObject container) { int spriteCount = spriteDefinitions.Length; int[] chunkData = chunk.spriteIds; /* For every row in the chunk... */ for (int y = 0; y < maxTilesY; ++y) { /* For every column in the chunk... */ for (int x = 0; x < maxTilesX; ++x) { int spriteId = chunkData[y * tilemap.partitionSizeX + x]; int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId); /* Handle if tile has no valid sprite. */ if (spriteIdx < 0 || spriteIdx >= spriteCount) { continue; } else if (tilemap.data.tilePrefabs[spriteIdx]) { continue; } tk2dSpriteDefinition spriteData = spriteDefinitions[spriteIdx]; /* If the tile is marked as User Defined, then add a box collider. */ if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Unset) { Vector3 newBoxColliderPosition = new Vector3( chunk.gameObject.transform.position.x + x * tileWidth, chunk.gameObject.transform.position.y + y * tileHeight, chunk.gameObject.transform.position.z ); GameObject newColliderObject; if (roundedBoxColliders) { newColliderObject = CreateRoundedBoxCollider(newBoxColliderPosition, "Rounded Box Collider " + x + " " + y); } else { newColliderObject = CreateBoxCollider(newBoxColliderPosition, "Box Collider " + x + " " + y); } newColliderObject.transform.parent = container.transform; newColliderObject.gameObject.AddComponent<FarseerFollowParent>(); newColliderObject.gameObject.AddComponent<FarseerEnableDisable>(); } } } }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY) { #if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) //////////////////////////////////////////////////////////////////////////////////////// // 1. Build local edge list //////////////////////////////////////////////////////////////////////////////////////// Vector2[] localVerts = new Vector2[0]; int[] localIndices = new int[0]; List<Vector2[]> mergedEdges = new List<Vector2[]>(); BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localVerts, ref localIndices); //////////////////////////////////////////////////////////////////////////////////////// // 2. Optimize //////////////////////////////////////////////////////////////////////////////////////// if (localIndices.Length > 4) { // Remove duplicate verts, reindex localVerts = WeldVertices(localVerts, ref localIndices); // Remove duplicate and back-to-back edges // Removes inside edges localIndices = RemoveDuplicateEdges(localIndices); } //////////////////////////////////////////////////////////////////////////////////////// // 3. Build and optimize an edge list //////////////////////////////////////////////////////////////////////////////////////// mergedEdges = MergeEdges( localVerts, localIndices ); //////////////////////////////////////////////////////////////////////////////////////// // 4. Build the edge colliders //////////////////////////////////////////////////////////////////////////////////////// if (chunk.meshCollider != null) { tk2dUtil.DestroyImmediate(chunk.meshCollider); chunk.meshCollider = null; } if (mergedEdges.Count == 0) { for (int i = 0; i < chunk.edgeColliders.Count; ++i) { if (chunk.edgeColliders[i] != null) { tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]); } } chunk.edgeColliders.Clear(); } else { int numEdges = mergedEdges.Count; // Destroy surplus for (int i = numEdges; i < chunk.edgeColliders.Count; ++i) { if (chunk.edgeColliders[i] != null) { tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]); } } int numToRemove = chunk.edgeColliders.Count - numEdges; if (numToRemove > 0) { chunk.edgeColliders.RemoveRange(chunk.edgeColliders.Count - numToRemove, numToRemove); } // Make sure existing ones are not null for (int i = 0; i < chunk.edgeColliders.Count; ++i) { if (chunk.edgeColliders[i] == null) { chunk.edgeColliders[i] = tk2dUtil.AddComponent<EdgeCollider2D>(chunk.gameObject); } } // Create missing while (chunk.edgeColliders.Count < numEdges) { chunk.edgeColliders.Add( tk2dUtil.AddComponent<EdgeCollider2D>(chunk.gameObject) ); } for (int i = 0; i < numEdges; ++i) { chunk.edgeColliders[i].points = mergedEdges[i]; } } #endif }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY) { // Build local mesh Vector3[] localMeshVertices = new Vector3[0]; int[] localMeshIndices = new int[0]; BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localMeshVertices, ref localMeshIndices); // only process when there are more than two triangles // avoids a lot of branches later if (localMeshIndices.Length > 6) { // Remove duplicate verts localMeshVertices = WeldVertices(localMeshVertices, ref localMeshIndices); // Remove duplicate and back-to-back faces // Removes inside faces localMeshIndices = RemoveDuplicateFaces(localMeshIndices); // Merge coplanar faces // Optimize (remove unused vertices, reindex) } #if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) foreach (EdgeCollider2D c2d in chunk.edgeColliders) { if (c2d != null) { tk2dUtil.DestroyImmediate(c2d); } } chunk.edgeColliders.Clear(); #endif if (localMeshVertices.Length > 0) { if (chunk.colliderMesh != null) { tk2dUtil.DestroyImmediate(chunk.colliderMesh); chunk.colliderMesh = null; } if (chunk.meshCollider == null) { chunk.meshCollider = chunk.gameObject.GetComponent <MeshCollider>(); if (chunk.meshCollider == null) { chunk.meshCollider = tk2dUtil.AddComponent <MeshCollider>(chunk.gameObject); } } chunk.colliderMesh = tk2dUtil.CreateMesh(); chunk.colliderMesh.vertices = localMeshVertices; chunk.colliderMesh.triangles = localMeshIndices; chunk.colliderMesh.RecalculateBounds(); chunk.meshCollider.sharedMesh = chunk.colliderMesh; } else { chunk.DestroyColliderData(tileMap); } }
// Builds an unoptimized mesh for this chunk static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector3[] vertices, ref int[] indices) { List<Vector3> vertexList = new List<Vector3>(); List<int> indexList = new List<int>(); int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Vector3 tileSize = tileMap.data.tileSize; var tilePrefabs = tileMap.data.tilePrefabs; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int tile = chunkData[y * tileMap.partitionSizeX + x]; Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) continue; if (tilePrefabs[tile]) continue; var spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[tile]; int baseVertexIndex = vertexList.Count; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0] + currentPos; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; vertexList.Add(new Vector3(min.x, min.y, min.z)); vertexList.Add(new Vector3(min.x, min.y, max.z)); vertexList.Add(new Vector3(max.x, min.y, min.z)); vertexList.Add(new Vector3(max.x, min.y, max.z)); vertexList.Add(new Vector3(min.x, max.y, min.z)); vertexList.Add(new Vector3(min.x, max.y, max.z)); vertexList.Add(new Vector3(max.x, max.y, min.z)); vertexList.Add(new Vector3(max.x, max.y, max.z)); // int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 }; int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 }; var srcIndices = indicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { indexList.Add(baseVertexIndex + srcIndices[i]); } } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { for (int i = 0; i < spriteData.colliderVertices.Length; ++i) { Vector3 pos = spriteData.colliderVertices[i] + currentPos; vertexList.Add(pos); } var srcIndices = spriteData.colliderIndicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { indexList.Add(baseVertexIndex + srcIndices[i]); } } } } vertices = vertexList.ToArray(); indices = indexList.ToArray(); }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { List <Vector3> meshVertices = new List <Vector3>(); List <Color> meshColors = new List <Color>(); List <Vector2> meshUvs = new List <Vector2>(); //List<int> meshIndices = new List<int>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Object[] tilePrefabs = tileMap.data.tilePrefabs; tk2dSpriteDefinition firstSprite = tileMap.SpriteCollectionInst.FirstValidDefinition; bool buildNormals = (firstSprite != null && firstSprite.normals != null && firstSprite.normals.Length > 0); Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white; // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty if (colorChunk == null || colorChunk.colors.Length == 0) { useColor = false; } int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out x0, out x1, out dx, out y0, out y1, out dy); float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); List <int>[] meshIndices = new List <int> [tileMap.SpriteCollectionInst.materials.Length]; for (int j = 0; j < meshIndices.Length; ++j) { meshIndices[j] = new List <int>(); } int colorChunkSize = tileMap.partitionSizeX + 1; for (int y = y0; y != y1; y += dy) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = x0; x != x1; x += dx) { int spriteId = spriteIds[y * tileMap.partitionSizeX + x]; int tile = BuilderUtil.GetTileFromRawTile(spriteId); bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) { continue; } if (skipPrefabs && tilePrefabs[tile]) { continue; } var sprite = tileMap.SpriteCollectionInst.spriteDefinitions[tile]; int baseVertex = meshVertices.Count; for (int v = 0; v < sprite.positions.Length; ++v) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, sprite, sprite.positions[v], flipH, flipV, rot90); if (useColor) { Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x]; Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1]; Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x]; Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)]; Vector3 centeredSpriteVertex = flippedPos - sprite.untrimmedBoundsData[0]; Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f; float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x); float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y); Color color = Color.Lerp( Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX), Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX), tileColorY); meshColors.Add(color); } else { meshColors.Add(clearColor); } meshVertices.Add(currentPos + flippedPos); meshUvs.Add(sprite.uvs[v]); } bool reverseIndices = false; // flipped? if (flipH) { reverseIndices = !reverseIndices; } if (flipV) { reverseIndices = !reverseIndices; } List <int> indices = meshIndices[sprite.materialId]; for (int i = 0; i < sprite.indices.Length; ++i) { int j = reverseIndices ? (sprite.indices.Length - 1 - i) : i; indices.Add(baseVertex + sprite.indices[j]); } } } if (chunk.mesh == null) { chunk.mesh = tk2dUtil.CreateMesh(); } chunk.mesh.vertices = meshVertices.ToArray(); chunk.mesh.uv = meshUvs.ToArray(); chunk.mesh.colors = meshColors.ToArray(); List <Material> materials = new List <Material>(); int materialId = 0; int subMeshCount = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { materials.Add(tileMap.SpriteCollectionInst.materialInsts[materialId]); subMeshCount++; } materialId++; } if (subMeshCount > 0) { chunk.mesh.subMeshCount = subMeshCount; chunk.gameObject.GetComponent <Renderer>().materials = materials.ToArray(); int subMeshId = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { chunk.mesh.SetTriangles(indices.ToArray(), subMeshId); subMeshId++; } } } chunk.mesh.RecalculateBounds(); if (buildNormals) { chunk.mesh.RecalculateNormals(); } var meshFilter = chunk.gameObject.GetComponent <MeshFilter>(); meshFilter.sharedMesh = chunk.mesh; }
private void Optimize(SpriteChunk chunk) { bool flag = true; foreach (int num in chunk.spriteIds) { if (num != -1) { flag = false; break; } } if (flag) { chunk.spriteIds = new int[0]; } }
// Builds an unoptimized mesh for this chunk static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector2[] vertices, ref int[] indices) { List <Vector2> verts = new List <Vector2>(); List <int> inds = new List <int>(); Vector2[] boxPos = new Vector2[4]; // used for box collider int[] boxInds = { 0, 1, 1, 2, 2, 3, 3, 0 }; int[] boxIndsFlipped = { 0, 3, 3, 2, 2, 1, 1, 0 }; int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Vector2 tileSize = new Vector3(tileMap.data.tileSize.x, tileMap.data.tileSize.y); var tilePrefabs = tileMap.data.tilePrefabs; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int spriteId = chunkData[y * tileMap.partitionSizeX + x]; int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId); Vector2 currentPos = new Vector2(tileSize.x * (x + xOffset), tileSize.y * y); if (spriteIdx < 0 || spriteIdx >= spriteCount) { continue; } if (tilePrefabs[spriteIdx]) { continue; } bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); bool reverseIndices = false; if (flipH) { reverseIndices = !reverseIndices; } if (flipV) { reverseIndices = !reverseIndices; } tk2dSpriteDefinition spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx]; int baseVertexIndex = verts.Count; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0]; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; boxPos[0] = new Vector2(min.x, min.y); boxPos[1] = new Vector2(max.x, min.y); boxPos[2] = new Vector2(max.x, max.y); boxPos[3] = new Vector2(min.x, max.y); for (int i = 0; i < 4; ++i) { verts.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, boxPos[i], flipH, flipV, rot90) + currentPos); } int[] boxIndices = reverseIndices ? boxIndsFlipped : boxInds; for (int i = 0; i < 8; ++i) { inds.Add(baseVertexIndex + boxIndices[i]); } } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { foreach (tk2dCollider2DData dat in spriteData.edgeCollider2D) { baseVertexIndex = verts.Count; foreach (Vector2 pos in dat.points) { verts.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos); } int numVerts = dat.points.Length; if (reverseIndices) { for (int i = numVerts - 1; i > 0; --i) { inds.Add(baseVertexIndex + i); inds.Add(baseVertexIndex + i - 1); } } else { for (int i = 0; i < numVerts - 1; ++i) { inds.Add(baseVertexIndex + i); inds.Add(baseVertexIndex + i + 1); } } } foreach (tk2dCollider2DData dat in spriteData.polygonCollider2D) { baseVertexIndex = verts.Count; foreach (Vector2 pos in dat.points) { verts.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos); } int numVerts = dat.points.Length; if (reverseIndices) { for (int i = numVerts; i > 0; --i) { inds.Add(baseVertexIndex + (i % numVerts)); inds.Add(baseVertexIndex + i - 1); } } else { for (int i = 0; i < numVerts; ++i) { inds.Add(baseVertexIndex + i); inds.Add(baseVertexIndex + (i + 1) % numVerts); } } } } } } vertices = verts.ToArray(); indices = inds.ToArray(); }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY) { #if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) //////////////////////////////////////////////////////////////////////////////////////// // 1. Build local edge list //////////////////////////////////////////////////////////////////////////////////////// Vector2[] localVerts = new Vector2[0]; int[] localIndices = new int[0]; List <Vector2[]> mergedEdges = new List <Vector2[]>(); BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localVerts, ref localIndices); //////////////////////////////////////////////////////////////////////////////////////// // 2. Optimize //////////////////////////////////////////////////////////////////////////////////////// if (localIndices.Length > 4) { // Remove duplicate verts, reindex localVerts = WeldVertices(localVerts, ref localIndices); // Remove duplicate and back-to-back edges // Removes inside edges localIndices = RemoveDuplicateEdges(localIndices); } //////////////////////////////////////////////////////////////////////////////////////// // 3. Build and optimize an edge list //////////////////////////////////////////////////////////////////////////////////////// mergedEdges = MergeEdges(localVerts, localIndices); //////////////////////////////////////////////////////////////////////////////////////// // 4. Build the edge colliders //////////////////////////////////////////////////////////////////////////////////////// if (chunk.meshCollider != null) { tk2dUtil.DestroyImmediate(chunk.meshCollider); chunk.meshCollider = null; } if (mergedEdges.Count == 0) { for (int i = 0; i < chunk.edgeColliders.Count; ++i) { if (chunk.edgeColliders[i] != null) { tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]); } } chunk.edgeColliders.Clear(); } else { int numEdges = mergedEdges.Count; // Destroy surplus for (int i = numEdges; i < chunk.edgeColliders.Count; ++i) { if (chunk.edgeColliders[i] != null) { tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]); } } int numToRemove = chunk.edgeColliders.Count - numEdges; if (numToRemove > 0) { chunk.edgeColliders.RemoveRange(chunk.edgeColliders.Count - numToRemove, numToRemove); } // Make sure existing ones are not null for (int i = 0; i < chunk.edgeColliders.Count; ++i) { if (chunk.edgeColliders[i] == null) { chunk.edgeColliders[i] = tk2dUtil.AddComponent <EdgeCollider2D>(chunk.gameObject); } } // Create missing while (chunk.edgeColliders.Count < numEdges) { chunk.edgeColliders.Add(tk2dUtil.AddComponent <EdgeCollider2D>(chunk.gameObject)); } for (int i = 0; i < numEdges; ++i) { chunk.edgeColliders[i].points = mergedEdges[i]; } } #endif }
/// Spawns all prefabs for a given chunk /// Expects the chunk to have a valid GameObject public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, int layer, int[] prefabCounts) { var chunkData = chunk.spriteIds; var tilePrefabs = tileMap.data.tilePrefabs; Vector3 tileSize = tileMap.data.tileSize; var parent = chunk.gameObject.transform; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int tile = GetTileFromRawTile(chunkData[y * tileMap.partitionSizeX + x]); if (tile < 0 || tile >= tilePrefabs.Length) { continue; } Object prefab = tilePrefabs[tile]; if (prefab != null) { prefabCounts[tile]++; GameObject instance = GetExistingTilePrefabInstance(tileMap, baseX + x, baseY + y, layer); bool foundExisting = (instance != null); #if UNITY_EDITOR if (instance != null) { if (UnityEditor.PrefabUtility.GetPrefabParent(instance) != prefab) { instance = null; } } #endif if (instance == null) { #if UNITY_EDITOR instance = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject; #else instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; #endif #if UNITY_EDITOR && !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) if (!Application.isPlaying) { UnityEditor.Undo.RegisterCreatedObjectUndo(instance, "Instantiated Prefab"); } #endif } if (instance != null) { GameObject prefabGameObject = prefab as GameObject; Vector3 pos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); bool enablePrefabOffset = false; var tileInfo = tileMap.data.GetTileInfoForSprite(tile); if (tileInfo != null) { enablePrefabOffset = tileInfo.enablePrefabOffset; } if (enablePrefabOffset && prefabGameObject != null) { pos += prefabGameObject.transform.position; } if (!foundExisting) { instance.name = prefab.name + " " + prefabCounts[tile].ToString(); } tk2dUtil.SetTransformParent(instance.transform, parent); instance.transform.localPosition = pos; // Add to tilePrefabs list TilePrefabsX.Add(baseX + x); TilePrefabsY.Add(baseY + y); TilePrefabsLayer.Add(layer); TilePrefabsInstance.Add(instance); } } } } }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { List <Vector3> meshVertices = new List <Vector3>(); List <Color> meshColors = new List <Color>(); List <Vector2> meshUvs = new List <Vector2>(); //List<int> meshIndices = new List<int>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int spriteCount = tileMap.spriteCollection.spriteDefinitions.Length; Object[] tilePrefabs = tileMap.data.tilePrefabs; Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white; // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty if (colorChunk == null || colorChunk.colors.Length == 0) { useColor = false; } int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out x0, out x1, out dx, out y0, out y1, out dy); List <int>[] meshIndices = new List <int> [tileMap.spriteCollection.materials.Length]; for (int j = 0; j < meshIndices.Length; ++j) { meshIndices[j] = new List <int>(); } int colorChunkSize = tileMap.partitionSizeX + 1; for (int y = y0; y != y1; y += dy) { for (int x = x0; x != x1; x += dx) { int tile = spriteIds[y * tileMap.partitionSizeX + x]; Vector3 currentPos = new Vector3(tileSize.x * x, tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) { continue; } if (skipPrefabs && tilePrefabs[tile]) { continue; } var sprite = tileMap.spriteCollection.spriteDefinitions[tile]; int baseVertex = meshVertices.Count; for (int v = 0; v < sprite.positions.Length; ++v) { if (useColor) { Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x]; Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1]; Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x]; Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)]; Vector3 centeredSpriteVertex = sprite.positions[v] - sprite.untrimmedBoundsData[0]; Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f; float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x); float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y); Color color = Color.Lerp( Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX), Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX), tileColorY); meshColors.Add(color); } else { meshColors.Add(clearColor); } meshVertices.Add(currentPos + sprite.positions[v]); meshUvs.Add(sprite.uvs[v]); } List <int> indices = meshIndices[sprite.materialId]; for (int i = 0; i < sprite.indices.Length; ++i) { indices.Add(baseVertex + sprite.indices[i]); } } } chunk.mesh.vertices = meshVertices.ToArray(); chunk.mesh.uv = meshUvs.ToArray(); chunk.mesh.colors = meshColors.ToArray(); List <Material> materials = new List <Material>(); int materialId = 0; int subMeshCount = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { materials.Add(tileMap.spriteCollection.materials[materialId]); subMeshCount++; } materialId++; } if (subMeshCount > 0) { chunk.mesh.subMeshCount = subMeshCount; chunk.gameObject.renderer.materials = materials.ToArray(); int subMeshId = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { chunk.mesh.SetTriangles(indices.ToArray(), subMeshId); subMeshId++; } } } chunk.mesh.RecalculateBounds(); }
// Builds an unoptimized mesh for this chunk static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ref Vector3[] vertices, ref int[] indices) { List <Vector3> vertexList = new List <Vector3>(); List <int> indexList = new List <int>(); int spriteCount = tileMap.spriteCollection.spriteDefinitions.Length; Vector3 tileSize = tileMap.data.tileSize; var tilePrefabs = tileMap.data.tilePrefabs; var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { for (int x = 0; x < tileMap.partitionSizeX; ++x) { int tile = chunkData[y * tileMap.partitionSizeX + x]; Vector3 currentPos = new Vector3(tileSize.x * x, tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) { continue; } if (tilePrefabs[tile]) { continue; } var spriteData = tileMap.spriteCollection.spriteDefinitions[tile]; int baseVertexIndex = vertexList.Count; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0] + currentPos; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; vertexList.Add(new Vector3(min.x, min.y, min.z)); vertexList.Add(new Vector3(min.x, min.y, max.z)); vertexList.Add(new Vector3(max.x, min.y, min.z)); vertexList.Add(new Vector3(max.x, min.y, max.z)); vertexList.Add(new Vector3(min.x, max.y, min.z)); vertexList.Add(new Vector3(min.x, max.y, max.z)); vertexList.Add(new Vector3(max.x, max.y, min.z)); vertexList.Add(new Vector3(max.x, max.y, max.z)); // int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 }; int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 }; var srcIndices = indicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { indexList.Add(baseVertexIndex + srcIndices[i]); } } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { for (int i = 0; i < spriteData.colliderVertices.Length; ++i) { Vector3 pos = spriteData.colliderVertices[i] + currentPos; vertexList.Add(pos); } var srcIndices = spriteData.colliderIndicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { indexList.Add(baseVertexIndex + srcIndices[i]); } } } } vertices = vertexList.ToArray(); indices = indexList.ToArray(); }
void Optimize(SpriteChunk chunk) { bool empty = true; foreach (var v in chunk.spriteIds) { if (v != -1) { empty = false; break; } } if (empty) chunk.spriteIds = new int[0]; }
/// Spawns all prefabs for a given chunk /// Expects the chunk to have a valid GameObject public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY) { var chunkData = chunk.spriteIds; var tilePrefabs = tileMap.data.tilePrefabs; Vector3 tileSize = tileMap.data.tileSize; int[] prefabCounts = new int[tilePrefabs.Length]; var parent = chunk.gameObject.transform; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int tile = chunkData[y * tileMap.partitionSizeX + x]; if (tile < 0 || tile >= tilePrefabs.Length) continue; Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); Object prefab = tilePrefabs[tile]; if (prefab != null) { prefabCounts[tile]++; #if UNITY_EDITOR && !(UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4) GameObject go = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject; #else GameObject go = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; #endif if (go) { go.name = prefab.name + " " + prefabCounts[tile].ToString(); // Position after transforming, as it is in local space go.transform.parent = parent; go.transform.localPosition = currentPos; go.transform.localRotation = Quaternion.identity; go.transform.localScale = Vector3.one; } } } } }
public static unsafe void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { int num2; int num3; int num4; int num5; int num6; int num7; List<Vector3> list = new List<Vector3>(); List<Color> list2 = new List<Color>(); List<Vector2> list3 = new List<Vector2>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int length = tileMap.SpriteCollectionInst.spriteDefinitions.Length; UnityEngine.Object[] tilePrefabs = tileMap.data.tilePrefabs; tk2dSpriteDefinition firstValidDefinition = tileMap.SpriteCollectionInst.FirstValidDefinition; bool flag = ((firstValidDefinition != null) && (firstValidDefinition.normals != null)) && (firstValidDefinition.normals.Length > 0); Color32 color = (!useColor || (tileMap.ColorChannel == null)) ? Color.white : tileMap.ColorChannel.clearColor; if ((colorChunk == null) || (colorChunk.colors.Length == 0)) { useColor = false; } BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out num2, out num3, out num4, out num5, out num6, out num7); float x = 0f; float y = 0f; tileMap.data.GetTileOffset(out x, out y); List<int>[] listArray = new List<int>[tileMap.SpriteCollectionInst.materials.Length]; for (int i = 0; i < listArray.Length; i++) { listArray[i] = new List<int>(); } int num11 = tileMap.partitionSizeX + 1; for (int j = num5; j != num6; j += num7) { float num13 = ((baseY + j) & 1) * x; for (int k = num2; k != num3; k += num4) { int rawTile = spriteIds[(j * tileMap.partitionSizeX) + k]; int tileFromRawTile = BuilderUtil.GetTileFromRawTile(rawTile); bool flipH = BuilderUtil.IsRawTileFlagSet(rawTile, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(rawTile, tk2dTileFlags.FlipY); bool flag4 = BuilderUtil.IsRawTileFlagSet(rawTile, tk2dTileFlags.Rot90); Vector3 vector2 = new Vector3(tileSize.x * (k + num13), tileSize.y * j, 0f); if (((tileFromRawTile >= 0) && (tileFromRawTile < length)) && (!skipPrefabs || (tilePrefabs[tileFromRawTile] == null))) { tk2dSpriteDefinition spriteDef = tileMap.SpriteCollectionInst.spriteDefinitions[tileFromRawTile]; int count = list.Count; for (int m = 0; m < spriteDef.positions.Length; m++) { Vector3 vector3 = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteDef, spriteDef.positions[m], flipH, flipV, flag4); if (useColor) { Color a = *((Color*) &(colorChunk.colors[(j * num11) + k])); Color b = *((Color*) &(colorChunk.colors[((j * num11) + k) + 1])); Color color4 = *((Color*) &(colorChunk.colors[((j + 1) * num11) + k])); Color color5 = *((Color*) &(colorChunk.colors[((j + 1) * num11) + (k + 1)])); Vector3 vector4 = vector3 - spriteDef.untrimmedBoundsData[0]; Vector3 vector5 = vector4 + ((Vector3) (tileMap.data.tileSize * 0.5f)); float t = Mathf.Clamp01(vector5.x / tileMap.data.tileSize.x); float num20 = Mathf.Clamp01(vector5.y / tileMap.data.tileSize.y); Color item = Color.Lerp(Color.Lerp(a, b, t), Color.Lerp(color4, color5, t), num20); list2.Add(item); } else { list2.Add((Color) color); } list.Add(vector2 + vector3); list3.Add(spriteDef.uvs[m]); } bool flag5 = false; if (flipH) { flag5 = !flag5; } if (flipV) { flag5 = !flag5; } List<int> list4 = listArray[spriteDef.materialId]; for (int n = 0; n < spriteDef.indices.Length; n++) { int num22 = !flag5 ? n : ((spriteDef.indices.Length - 1) - n); list4.Add(count + spriteDef.indices[num22]); } } } } if (chunk.mesh == null) { chunk.mesh = tk2dUtil.CreateMesh(); } chunk.mesh.vertices = list.ToArray(); chunk.mesh.uv = list3.ToArray(); chunk.mesh.colors = list2.ToArray(); List<Material> list5 = new List<Material>(); int index = 0; int num24 = 0; foreach (List<int> list6 in listArray) { if (list6.Count > 0) { list5.Add(tileMap.SpriteCollectionInst.materialInsts[index]); num24++; } index++; } if (num24 > 0) { chunk.mesh.subMeshCount = num24; chunk.gameObject.renderer.materials = list5.ToArray(); int submesh = 0; foreach (List<int> list7 in listArray) { if (list7.Count > 0) { chunk.mesh.SetTriangles(list7.ToArray(), submesh); submesh++; } } } chunk.mesh.RecalculateBounds(); if (flag) { chunk.mesh.RecalculateNormals(); } chunk.gameObject.GetComponent<MeshFilter>().sharedMesh = chunk.mesh; }
// Builds an unoptimized mesh for this chunk static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector3[] vertices, ref int[] indices) { List<Vector3> vertexList = new List<Vector3>(); List<int> indexList = new List<int>(); int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Vector3 tileSize = tileMap.data.tileSize; var tilePrefabs = tileMap.data.tilePrefabs; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int spriteId = chunkData[y * tileMap.partitionSizeX + x]; int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId); Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (spriteIdx < 0 || spriteIdx >= spriteCount) continue; if (tilePrefabs[spriteIdx]) continue; bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); bool reverseIndices = false; if (flipH) reverseIndices = !reverseIndices; if (flipV) reverseIndices = !reverseIndices; var spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx]; int baseVertexIndex = vertexList.Count; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0]; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; Vector3[] pos = new Vector3[8]; pos[0] = new Vector3(min.x, min.y, min.z); pos[1] = new Vector3(min.x, min.y, max.z); pos[2] = new Vector3(max.x, min.y, min.z); pos[3] = new Vector3(max.x, min.y, max.z); pos[4] = new Vector3(min.x, max.y, min.z); pos[5] = new Vector3(min.x, max.y, max.z); pos[6] = new Vector3(max.x, max.y, min.z); pos[7] = new Vector3(max.x, max.y, max.z); for (int i = 0; i < 8; ++i) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos[i], flipH, flipV, rot90); vertexList.Add (flippedPos + currentPos); } // int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 }; int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 }; var srcIndices = indicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { int j = reverseIndices ? (srcIndices.Length - 1 - i) : i; indexList.Add(baseVertexIndex + srcIndices[j]); } } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { for (int i = 0; i < spriteData.colliderVertices.Length; ++i) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, spriteData.colliderVertices[i], flipH, flipV, rot90); vertexList.Add(flippedPos + currentPos); } var srcIndices = spriteData.colliderIndicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { int j = reverseIndices ? (srcIndices.Length - 1 - i) : i; indexList.Add(baseVertexIndex + srcIndices[j]); } } } } vertices = vertexList.ToArray(); indices = indexList.ToArray(); }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { List<Vector3> meshVertices = new List<Vector3>(); List<Color> meshColors = new List<Color>(); List<Vector2> meshUvs = new List<Vector2>(); //List<int> meshIndices = new List<int>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Object[] tilePrefabs = tileMap.data.tilePrefabs; tk2dSpriteDefinition firstSprite = tileMap.SpriteCollectionInst.FirstValidDefinition; bool buildNormals = (firstSprite != null && firstSprite.normals != null && firstSprite.normals.Length > 0); Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white; // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty if (colorChunk == null || colorChunk.colors.Length == 0) useColor = false; int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out x0, out x1, out dx, out y0, out y1, out dy); float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); List<int>[] meshIndices = new List<int>[tileMap.SpriteCollectionInst.materials.Length]; for (int j = 0; j < meshIndices.Length; ++j) meshIndices[j] = new List<int>(); int colorChunkSize = tileMap.partitionSizeX + 1; for (int y = y0; y != y1; y += dy) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = x0; x != x1; x += dx) { int spriteId = spriteIds[y * tileMap.partitionSizeX + x]; int tile = BuilderUtil.GetTileFromRawTile(spriteId); bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) continue; if (skipPrefabs && tilePrefabs[tile]) continue; var sprite = tileMap.SpriteCollectionInst.spriteDefinitions[tile]; int baseVertex = meshVertices.Count; for (int v = 0; v < sprite.positions.Length; ++v) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, sprite, sprite.positions[v], flipH, flipV, rot90); if (useColor) { Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x]; Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1]; Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x]; Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)]; Vector3 centeredSpriteVertex = flippedPos - sprite.untrimmedBoundsData[0]; Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f; float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x); float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y); Color color = Color.Lerp( Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX), Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX), tileColorY); meshColors.Add(color); } else { meshColors.Add(clearColor); } meshVertices.Add(currentPos + flippedPos); meshUvs.Add(sprite.uvs[v]); } bool reverseIndices = false; // flipped? if (flipH) reverseIndices = !reverseIndices; if (flipV) reverseIndices = !reverseIndices; List<int> indices = meshIndices[sprite.materialId]; for (int i = 0; i < sprite.indices.Length; ++i) { int j = reverseIndices ? (sprite.indices.Length - 1 - i) : i; indices.Add(baseVertex + sprite.indices[j]); } } } if (chunk.mesh == null) chunk.mesh = tk2dUtil.CreateMesh(); chunk.mesh.vertices = meshVertices.ToArray(); chunk.mesh.uv = meshUvs.ToArray(); chunk.mesh.colors = meshColors.ToArray(); List<Material> materials = new List<Material>(); int materialId = 0; int subMeshCount = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { materials.Add(tileMap.SpriteCollectionInst.materialInsts[materialId]); subMeshCount++; } materialId++; } if (subMeshCount > 0) { chunk.mesh.subMeshCount = subMeshCount; chunk.gameObject.renderer.materials = materials.ToArray(); int subMeshId = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { chunk.mesh.SetTriangles(indices.ToArray(), subMeshId); subMeshId++; } } } chunk.mesh.RecalculateBounds(); if (buildNormals) { chunk.mesh.RecalculateNormals(); } var meshFilter = chunk.gameObject.GetComponent<MeshFilter>(); meshFilter.sharedMesh = chunk.mesh; }
public static void BuildPolygonCollidersForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY) { // Clear colliders EdgeCollider2D[] edgeColliders = chunk.gameObject.GetComponents <EdgeCollider2D>(); foreach (var ec in edgeColliders) { tk2dUtil.DestroyImmediate(ec); } chunk.edgeColliders.Clear(); PolygonCollider2D[] polyColliders = chunk.gameObject.GetComponents <PolygonCollider2D>(); foreach (var pc in polyColliders) { tk2dUtil.DestroyImmediate(pc); } Vector2[] boxPos = new Vector2[4]; // used for box collider List <List <Vector2> > paths = new List <List <Vector2> >(); int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Vector2 tileSize = new Vector3(tileMap.data.tileSize.x, tileMap.data.tileSize.y); var tilePrefabs = tileMap.data.tilePrefabs; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); List <Vector2> cachedPoints = new List <Vector2>(); var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int spriteId = chunkData[y * tileMap.partitionSizeX + x]; int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId); Vector2 currentPos = new Vector2(tileSize.x * (x + xOffset), tileSize.y * y); if (spriteIdx < 0 || spriteIdx >= spriteCount) { continue; } if (tilePrefabs[spriteIdx]) { continue; } bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); bool reverseIndices = false; if (flipH) { reverseIndices = !reverseIndices; } if (flipV) { reverseIndices = !reverseIndices; } tk2dSpriteDefinition spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx]; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0]; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; boxPos[0] = new Vector2(min.x, min.y); boxPos[1] = new Vector2(max.x, min.y); boxPos[2] = new Vector2(max.x, max.y); boxPos[3] = new Vector2(min.x, max.y); List <Vector2> thisList = new List <Vector2>(); int start = reverseIndices ? 3 : 0; int end = reverseIndices ? -1 : 4; int inc = reverseIndices ? -1 : 1; for (int i = start; i != end; i += inc) { thisList.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, boxPos[i], flipH, flipV, rot90) + currentPos); } paths.Add(thisList); } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { cachedPoints.Clear(); List <Vector2> points = new List <Vector2>(); foreach (tk2dCollider2DData dat in spriteData.polygonCollider2D) { foreach (Vector2 pos in dat.points) { cachedPoints.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos); } int numVerts = dat.points.Length; if (reverseIndices) { for (int i = cachedPoints.Count - 1; i >= 0; --i) { points.Add(cachedPoints[i]); } } else { for (int i = 0; i < numVerts; ++i) { points.Add(cachedPoints[i]); } } } paths.Add(points); } } } int numPathsPerObject = 64; int startPath = 0; int pathsRemaining = paths.Count; while (pathsRemaining > 0) { int pathsThisRound = Mathf.Min(numPathsPerObject, pathsRemaining); PolygonCollider2D newPc = chunk.gameObject.AddComponent <PolygonCollider2D>(); newPc.pathCount = pathsThisRound; for (int i = 0; i < pathsThisRound; ++i) { newPc.SetPath(i, paths[startPath + i].ToArray()); } startPath += pathsThisRound; pathsRemaining -= pathsThisRound; } }
/// Spawns all prefabs for a given chunk /// Expects the chunk to have a valid GameObject public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, int layer, int[] prefabCounts) { var chunkData = chunk.spriteIds; var tilePrefabs = tileMap.data.tilePrefabs; Vector3 tileSize = tileMap.data.tileSize; var parent = chunk.gameObject.transform; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int tile = GetTileFromRawTile(chunkData[y * tileMap.partitionSizeX + x]); if (tile < 0 || tile >= tilePrefabs.Length) continue; Object prefab = tilePrefabs[tile]; if (prefab != null) { prefabCounts[tile]++; GameObject instance = GetExistingTilePrefabInstance(tileMap, baseX + x, baseY + y, layer); bool foundExisting = (instance != null); #if UNITY_EDITOR if (instance != null) { if (UnityEditor.PrefabUtility.GetPrefabParent(instance) != prefab) { instance = null; } } #endif if (instance == null) { #if UNITY_EDITOR instance = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject; #else instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject; #endif #if UNITY_EDITOR && !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) if (!Application.isPlaying) { UnityEditor.Undo.RegisterCreatedObjectUndo(instance, "Instantiated Prefab"); } #endif } if (instance != null) { GameObject prefabGameObject = prefab as GameObject; Vector3 pos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); bool enablePrefabOffset = false; var tileInfo = tileMap.data.GetTileInfoForSprite(tile); if (tileInfo != null) enablePrefabOffset = tileInfo.enablePrefabOffset; if (enablePrefabOffset && prefabGameObject != null) pos += prefabGameObject.transform.position; if (!foundExisting) instance.name = prefab.name + " " + prefabCounts[tile].ToString(); tk2dUtil.SetTransformParent(instance.transform, parent); instance.transform.localPosition = pos; // Add to tilePrefabs list TilePrefabsX.Add(baseX + x); TilePrefabsY.Add(baseY + y); TilePrefabsLayer.Add(layer); TilePrefabsInstance.Add(instance); } } } } }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { List<Vector3> meshVertices = new List<Vector3>(); List<Color> meshColors = new List<Color>(); List<Vector2> meshUvs = new List<Vector2>(); //List<int> meshIndices = new List<int>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int spriteCount = tileMap.spriteCollection.spriteDefinitions.Length; Object[] tilePrefabs = tileMap.data.tilePrefabs; Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white; // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty if (colorChunk == null || colorChunk.colors.Length == 0) useColor = false; int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out x0, out x1, out dx, out y0, out y1, out dy); List<int>[] meshIndices = new List<int>[tileMap.spriteCollection.materials.Length]; for (int j = 0; j < meshIndices.Length; ++j) meshIndices[j] = new List<int>(); int colorChunkSize = tileMap.partitionSizeX + 1; for (int y = y0; y != y1; y += dy) { for (int x = x0; x != x1; x += dx) { int tile = spriteIds[y * tileMap.partitionSizeX + x]; Vector3 currentPos = new Vector3(tileSize.x * x, tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) continue; if (skipPrefabs && tilePrefabs[tile]) continue; var sprite = tileMap.spriteCollection.spriteDefinitions[tile]; int baseVertex = meshVertices.Count; for (int v = 0; v < sprite.positions.Length; ++v) { if (useColor) { Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x]; Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1]; Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x]; Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)]; Vector3 centeredSpriteVertex = sprite.positions[v] - sprite.untrimmedBoundsData[0]; Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f; float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x); float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y); Color color = Color.Lerp( Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX), Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX), tileColorY); meshColors.Add(color); } else { meshColors.Add(clearColor); } meshVertices.Add(currentPos + sprite.positions[v]); meshUvs.Add(sprite.uvs[v]); } List<int> indices = meshIndices[sprite.materialId]; for (int i = 0; i < sprite.indices.Length; ++i) indices.Add(baseVertex + sprite.indices[i]); } } if (chunk.mesh == null) chunk.mesh = tileMap.GetOrCreateMesh(); chunk.mesh.vertices = meshVertices.ToArray(); chunk.mesh.uv = meshUvs.ToArray(); chunk.mesh.colors = meshColors.ToArray(); List<Material> materials = new List<Material>(); int materialId = 0; int subMeshCount = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { materials.Add(tileMap.spriteCollection.materials[materialId]); subMeshCount++; } materialId++; } if (subMeshCount > 0) { chunk.mesh.subMeshCount = subMeshCount; chunk.gameObject.renderer.materials = materials.ToArray(); int subMeshId = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { chunk.mesh.SetTriangles(indices.ToArray(), subMeshId); subMeshId++; } } } chunk.mesh.RecalculateBounds(); if (tileMap.serializeRenderData) chunk.mesh.RecalculateNormals(); var meshFilter = chunk.gameObject.GetComponent<MeshFilter>(); meshFilter.sharedMesh = chunk.mesh; }
// Builds an unoptimized mesh for this chunk static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector2[] vertices, ref int[] indices) { List<Vector2> verts = new List<Vector2>(); List<int> inds = new List<int>(); Vector2[] boxPos = new Vector2[4]; // used for box collider int[] boxInds = { 0, 1, 1, 2, 2, 3, 3, 0 }; int[] boxIndsFlipped = { 0, 3, 3, 2, 2, 1, 1, 0 }; int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Vector2 tileSize = new Vector3(tileMap.data.tileSize.x, tileMap.data.tileSize.y); var tilePrefabs = tileMap.data.tilePrefabs; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int spriteId = chunkData[y * tileMap.partitionSizeX + x]; int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId); Vector2 currentPos = new Vector2(tileSize.x * (x + xOffset), tileSize.y * y); if (spriteIdx < 0 || spriteIdx >= spriteCount) continue; if (tilePrefabs[spriteIdx]) continue; bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); bool reverseIndices = false; if (flipH) reverseIndices = !reverseIndices; if (flipV) reverseIndices = !reverseIndices; tk2dSpriteDefinition spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx]; int baseVertexIndex = verts.Count; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0]; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; boxPos[0] = new Vector2(min.x, min.y); boxPos[1] = new Vector2(max.x, min.y); boxPos[2] = new Vector2(max.x, max.y); boxPos[3] = new Vector2(min.x, max.y); for (int i = 0; i < 4; ++i) { verts.Add( BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, boxPos[i], flipH, flipV, rot90) + currentPos ); } int[] boxIndices = reverseIndices ? boxIndsFlipped : boxInds; for (int i = 0; i < 8; ++i) { inds.Add( baseVertexIndex + boxIndices[i] ); } } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { foreach (tk2dCollider2DData dat in spriteData.edgeCollider2D) { foreach (Vector2 pos in dat.points) { verts.Add( BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos ); } int numVerts = dat.points.Length; if (reverseIndices) { for (int i = numVerts - 1; i > 0; --i) { inds.Add( baseVertexIndex + i ); inds.Add( baseVertexIndex + i - 1 ); } } else { for (int i = 0; i < numVerts - 1; ++i) { inds.Add(baseVertexIndex + i); inds.Add(baseVertexIndex + i + 1); } } } foreach (tk2dCollider2DData dat in spriteData.polygonCollider2D) { foreach (Vector2 pos in dat.points) { verts.Add( BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos ); } int numVerts = dat.points.Length; if (reverseIndices) { for (int i = numVerts; i > 0; --i) { inds.Add( baseVertexIndex + (i % numVerts) ); inds.Add( baseVertexIndex + i - 1 ); } } else { for (int i = 0; i < numVerts; ++i) { inds.Add(baseVertexIndex + i); inds.Add(baseVertexIndex + (i + 1) % numVerts); } } } } } } vertices = verts.ToArray(); indices = inds.ToArray(); }
// Builds an unoptimized mesh for this chunk static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector3[] vertices, ref int[] indices) { List <Vector3> vertexList = new List <Vector3>(); List <int> indexList = new List <int>(); int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Vector3 tileSize = tileMap.data.tileSize; var tilePrefabs = tileMap.data.tilePrefabs; float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); var chunkData = chunk.spriteIds; for (int y = 0; y < tileMap.partitionSizeY; ++y) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = 0; x < tileMap.partitionSizeX; ++x) { int spriteId = chunkData[y * tileMap.partitionSizeX + x]; int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId); Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (spriteIdx < 0 || spriteIdx >= spriteCount) { continue; } if (tilePrefabs[spriteIdx]) { continue; } bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); bool reverseIndices = false; if (flipH) { reverseIndices = !reverseIndices; } if (flipV) { reverseIndices = !reverseIndices; } var spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx]; int baseVertexIndex = vertexList.Count; if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box) { Vector3 origin = spriteData.colliderVertices[0]; Vector3 extents = spriteData.colliderVertices[1]; Vector3 min = origin - extents; Vector3 max = origin + extents; Vector3[] pos = new Vector3[8]; pos[0] = new Vector3(min.x, min.y, min.z); pos[1] = new Vector3(min.x, min.y, max.z); pos[2] = new Vector3(max.x, min.y, min.z); pos[3] = new Vector3(max.x, min.y, max.z); pos[4] = new Vector3(min.x, max.y, min.z); pos[5] = new Vector3(min.x, max.y, max.z); pos[6] = new Vector3(max.x, max.y, min.z); pos[7] = new Vector3(max.x, max.y, max.z); for (int i = 0; i < 8; ++i) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos[i], flipH, flipV, rot90); vertexList.Add(flippedPos + currentPos); } // int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 }; int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 }; var srcIndices = indicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { int j = reverseIndices ? (srcIndices.Length - 1 - i) : i; indexList.Add(baseVertexIndex + srcIndices[j]); } } else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh) { for (int i = 0; i < spriteData.colliderVertices.Length; ++i) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, spriteData.colliderVertices[i], flipH, flipV, rot90); vertexList.Add(flippedPos + currentPos); } var srcIndices = spriteData.colliderIndicesFwd; for (int i = 0; i < srcIndices.Length; ++i) { int j = reverseIndices ? (srcIndices.Length - 1 - i) : i; indexList.Add(baseVertexIndex + srcIndices[j]); } } } } vertices = vertexList.ToArray(); indices = indexList.ToArray(); }