Пример #1
0
    void GenerateTilemap()
    {
        if (meshObject.GetComponent <MeshFilter>() != null)
        {
            DestroyImmediate(meshObject.GetComponent <MeshFilter>());
            mesh = null;
        }

        meshFilter = meshObject.AddComponent <MeshFilter>();
        mesh       = new Mesh();

        if (meshObject.GetComponent <MeshCollider>() == null)
        {
            if (_generateMeshCollider)
            {
                meshCollider = meshObject.AddComponent <MeshCollider>();
            }
        }
        else if (!_generateMeshCollider)
        {
            DestroyImmediate(meshObject.GetComponent <MeshCollider>());
            meshCollider = null;
        }
        else if (_generateMeshCollider)
        {
            meshCollider = meshObject.GetComponent <MeshCollider>();
        }

        if (meshObject.GetComponent <MeshRenderer>() == null)
        {
            meshRenderer = meshObject.AddComponent <MeshRenderer>();
        }
        else
        {
            meshRenderer = meshObject.GetComponent <MeshRenderer>();
        }

        List <Vector3> vertices = new List <Vector3>();
        List <Vector2> uvs      = new List <Vector2>();

        // Tileset id, Triangles List (each tileset = submesh)
        Dictionary <int, List <int> > submeshesTriangles = new Dictionary <int, List <int> >();

        float actualZ       = 0;
        int   triangleFaces = -1;

        for (int layerIdx = 0; layerIdx < layers.Count; layerIdx++)
        {
            actualZ += _layerZ;
            TilelayerData layer = layers[layerIdx];

            for (int row = 1; row <= tilemapHeight; ++row)
            {
                for (int col = 0; col < tilemapWidth; ++col)
                {
                    // Get GID
                    int gid = layer.gids[row - 1, col];
                    if (gid == 0)
                    {
                        continue;
                    }

                    // Get tileset for this gid
                    int         tilesetId          = tilesetIdToGid[gid];
                    TilesetData tileset            = tilesets[tilesetId];
                    int         textureTilesPerRow = tileset.tilesPerRow;
                    int         firstGid           = tileset.firstgid;
                    float       textureWidth       = tileset.imagewidth;
                    float       textureHeight      = tileset.imageheight;

                    if (!submeshesTriangles.ContainsKey(tilesetId))
                    {
                        submeshesTriangles.Add(tilesetId, new List <int>());
                    }

                    // Tile position
                    Vector3 pos0 = new Vector3(col * scaleX, (-(tileHeight * row - anchorY) * scale), 0);
                    Vector3 pos1 = pos0 + new Vector3(scaleX, scaleY, 0);

                    // Vertices
                    Vector3 p0 = new Vector3(pos0.x, pos0.y, actualZ);
                    Vector3 p1 = new Vector3(pos1.x, pos0.y, actualZ);
                    Vector3 p2 = new Vector3(pos0.x, pos1.y, actualZ);
                    Vector3 p3 = new Vector3(pos1.x, pos1.y, actualZ);

                    vertices.Add(p0);
                    vertices.Add(p1);
                    vertices.Add(p2);
                    vertices.Add(p3);

                    // Triangles
                    triangleFaces += 4;

                    submeshesTriangles[tilesetId].Add(triangleFaces - 3);
                    submeshesTriangles[tilesetId].Add(triangleFaces - 1);
                    submeshesTriangles[tilesetId].Add(triangleFaces - 2);
                    submeshesTriangles[tilesetId].Add(triangleFaces - 2);
                    submeshesTriangles[tilesetId].Add(triangleFaces - 1);
                    submeshesTriangles[tilesetId].Add(triangleFaces);

                    // UV
                    int equivalentGidFromFirstRow = gid - firstGid + 1;
                    int tilesRow = 1;

                    for (; equivalentGidFromFirstRow > (textureTilesPerRow); equivalentGidFromFirstRow -= (textureTilesPerRow))
                    {
                        tilesRow++;
                    }

                    float tileX           = ((equivalentGidFromFirstRow - 1) * (tileWidth + tileset.spacing)) + tileset.margin;
                    float tileYBottomLeft = (((tileHeight + tileset.spacing) * tilesRow) - tileset.spacing) + tileset.margin;

                    float pixelMinX = textureWidth;
                    float pixelMinY = textureHeight;

                    if (tileX != 0f)
                    {
                        pixelMinX = tileX / pixelMinX;
                    }
                    if (tileYBottomLeft != 0f)
                    {
                        pixelMinY = tileYBottomLeft / pixelMinY;
                    }

                    Vector2 pixelMin  = new Vector2(pixelMinX, 1.0f - pixelMinY);
                    Vector2 pixelDims = new Vector2((tileWidth / textureWidth), (tileHeight / textureHeight));

                    Vector2 min = pixelMin;

                    // Amount of UV's have to match the amount of verts
                    // And their winding.
                    // Fix gaps with eps: http://forum.unity3d.com/threads/41187-Web-demo-of-my-2D-platformer?p=263666&viewfull=1#post263666
                    float eps = BleedingOffset;
                    uvs.Add(min + new Vector2(pixelDims.x * 0.0f + eps, pixelDims.y * 0.0f + eps));
                    uvs.Add(min + new Vector2(pixelDims.x * 1.0f - eps, pixelDims.y * 0.0f + eps));
                    uvs.Add(min + new Vector2(pixelDims.x * 0.0f + eps, pixelDims.y * 1.0f - eps));
                    uvs.Add(min + new Vector2(pixelDims.x * 1.0f - eps, pixelDims.y * 1.0f - eps));
                }
            }
        }         // end iterate layers

        mesh.vertices = vertices.ToArray();
        mesh.uv       = uvs.ToArray();

        // Only one tileset, no need for more than one submesh
        if (_amountTilesets == 1)
        {
            mesh.triangles = submeshesTriangles[0].ToArray();
        }
        // A submesh to each tileset
        else
        {
            mesh.subMeshCount = _amountTilesets;

            for (int tilesetId = 0; tilesetId < _amountTilesets; tilesetId++)
            {
                if (submeshesTriangles.ContainsKey(tilesetId))
                {
                    mesh.SetTriangles(submeshesTriangles[tilesetId].ToArray(), tilesetId);
                }
                else
                {
                    mesh.SetTriangles(new int[0], tilesetId);
                }
            }
        }

        meshFilter.mesh = mesh;

        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        ;

        if (_generateMeshCollider)
        {
            meshCollider.sharedMesh = null;
            meshCollider.sharedMesh = mesh;
        }

        meshRenderer.materials = TilesetsMaterials;
    }
Пример #2
0
    void ImportTiledXML()
    {
        if (LoadTiledXML())
        {
            if (_xml.DocumentElement.Name == "map")
            {
                tilemapWidth  = System.Convert.ToInt32(_xml.DocumentElement.Attributes["width"].Value);
                tilemapHeight = System.Convert.ToInt32(_xml.DocumentElement.Attributes["height"].Value);
                tileWidth     = System.Convert.ToInt32(_xml.DocumentElement.Attributes["tilewidth"].Value);
                tileHeight    = System.Convert.ToInt32(_xml.DocumentElement.Attributes["tileheight"].Value);

                scaleX = tileWidth * scale;
                scaleY = tileHeight * scale;

                anchorX = 0;
                anchorY = tileHeight;

                XmlNodeList tilesetsNodes = _xml.DocumentElement.SelectNodes("tileset");
                XmlNodeList layersNodes   = _xml.DocumentElement.SelectNodes("layer");

                XmlNode subNode    = null;
                XmlNode subSubNode = null;

                tilesets       = new List <TilesetData>();
                layers         = new List <TilelayerData>();
                tilesetIdToGid = new Dictionary <int, int>();

                for (int tilesetId = 0; tilesetId < tilesetsNodes.Count; ++tilesetId)
                {
                    subNode = tilesetsNodes[tilesetId];

                    TilesetData tileset = new TilesetData();
                    tileset.name       = subNode.Attributes["name"].Value;
                    tileset.firstgid   = System.Convert.ToInt32(subNode.Attributes["firstgid"].Value);
                    tileset.tilewidth  = System.Convert.ToInt32(subNode.Attributes["tilewidth"].Value);
                    tileset.tileheight = System.Convert.ToInt32(subNode.Attributes["tileheight"].Value);

                    if (subNode.Attributes["margin"] != null)
                    {
                        tileset.margin = System.Convert.ToInt32(subNode.Attributes["margin"].Value);
                    }
                    else
                    {
                        tileset.margin = 0;
                    }

                    if (subNode.Attributes["spacing"] != null)
                    {
                        tileset.spacing = System.Convert.ToInt32(subNode.Attributes["spacing"].Value);
                    }
                    else
                    {
                        tileset.spacing = 0;
                    }

                    subSubNode          = subNode.SelectSingleNode("image");
                    tileset.imagesource = subSubNode.Attributes["source"].Value;
                    tileset.imagewidth  = (float)System.Convert.ToDouble(subSubNode.Attributes["width"].Value);
                    tileset.imageheight = (float)System.Convert.ToDouble(subSubNode.Attributes["height"].Value);

                    tileset.tilesPerRow = (int)((tileset.imagewidth - tileset.margin * 2 + tileset.spacing) /
                                                (tileset.tilewidth + tileset.spacing)
                                                );

                    tileset.tilesPerColumn = (int)((tileset.imageheight - tileset.margin * 2 + tileset.spacing) /
                                                   (tileset.tileheight + tileset.spacing)
                                                   );

                    tileset.amountTiles = tileset.tilesPerRow * tileset.tilesPerColumn;

                    tilesets.Add(tileset);

                    // Map each gid of this tileset with the Tileset ID, so when building the tilemap
                    // mesh, we can easily grab the tileset related to the gid.
                    for (int gid = tileset.firstgid; gid <= (tileset.firstgid + tileset.amountTiles - 1); gid++)
                    {
                        tilesetIdToGid.Add(gid, tilesetId);
                    }
                }

                for (int layerId = 0; layerId < layersNodes.Count; ++layerId)
                {
                    subNode = layersNodes[layerId];

                    TilelayerData layer = new TilelayerData();
                    layer.name = subNode.Attributes["name"].Value;

                    XmlNodeList gidsNodes = subNode.SelectNodes("data/tile");

                    int gidRow    = 0;
                    int gidColumn = 0;

                    layer.gids = new int[tilemapWidth, tilemapHeight];

                    for (int gi = 0; gi < gidsNodes.Count; gi++)
                    {
                        layer.gids[gidRow, gidColumn] = System.Convert.ToInt32(gidsNodes[gi].Attributes["gid"].Value);
                        gidColumn++;

                        if ((gi + 1) % tilemapWidth == 0)
                        {
                            gidRow++;
                            gidColumn = 0;
                        }
                    }

                    layers.Add(layer);
                }

                _amountTilesets = tilesets.Count;

                if (TilesetsTextures != null && TilesetsTextures.Length != _amountTilesets)
                {
                    for (int i = 0; i < TilesetsMaterials.Length; i++)
                    {
                        if (TilesetsMaterials[i] != null)
                        {
                            DestroyImmediate(TilesetsMaterials[i]);
                        }
                    }

                    TilesetsTextures  = null;
                    TilesetsMaterials = null;
                }

                if (TilesetsTextures == null)
                {
                    TilesetsTextures  = new Texture[_amountTilesets];
                    TilesetsMaterials = new Material[TilesetsTextures.Length];
                }
            }
        }
    }