Seanba / Tiled2Unity

Export Tiled Map Editor (TMX) files into Unity
Other
497 stars 120 forks source link

How to combine same objects into one larger one? #119

Closed sghanta closed 7 years ago

sghanta commented 7 years ago

I was looking for a way to combine two adjacent similar objects into one large object over two tiles. For example if there is a body of water, I want to combine a majority of it into one large water object. I guess there will be uneven edges that I will have to have multiple objects for. I have a pretty large map and i don't know if having a lot of objects will cause issues later. Is this something I can do with automap?

Jazzepi commented 7 years ago

Tiled2unity combines adjacent tiles with colliders if the colliders in the adjacent tiles have the same type.

http://www.seanba.com/object-type-support.html

In short you have to

  1. Create the type in tiled.
  2. Edit the collider for your tile and give it the type that it should be (water, forest etc.)

Once you do that when you import the map tiled2unity will build one big collider for every continguous set of tiles with matching collider types.

sghanta commented 7 years ago

@Jazzepi Thanks so much! I tried that and got large objects instead of so many little ones. I added custom properties like unity:isTrigger on the object types editor, but they are not being imported into unity correctly. I exported the object types xml, but that did not do the trick either. I have two custom properties on the water object type (Terrain and unity:isTrigger). This is my code for the custom importer.

[Tiled2Unity.CustomTiledImporter]
public class CustomImporter_Objects : Tiled2Unity.ICustomTiledImporter
{

    public void HandleCustomProperties(GameObject gameObject,
        IDictionary<string, string> customProperties)
    {
        if (customProperties.ContainsKey("Terrain"))
        {
            InteractableTile tile = gameObject.AddComponent<InteractableTile>();
            tile.TileType = customProperties["Terrain"];
        }
    }

    public void CustomizePrefab(GameObject prefab)
    {
        // Do nothing
    }
}

What am I missing?

Jazzepi commented 7 years ago

@sghanta I'll take a look at custom properties later. I haven't had a chance to use that feature yet.

You might want to put some console log statements in there and see if that code is actually being run. And then you could interrogate the if (customProperties.ContainsKey("Terrain")) line of code. I would guess off the top of my head that the customProperties object contains something slightly different than you expect.

sghanta commented 7 years ago

@Jazzepi Thanks for your help! I'll let you know if I find a solution.

Jazzepi commented 7 years ago

@sghanta Some thoughts.

  1. I don't think you should have to do anything to handle the unity:isTrigger since that's a type supported out of the box. I think tiles should have the trigger value set to true after you import.
  2. The code that's loading your CustomImporter is here. What you did looks right. It appears that the code opens up all the assemblies it can find and looks for implementations of the interface. Were you able to confirm if it's actually loading/running your class? https://github.com/Seanba/Tiled2Unity/blob/02399cdaa5243b63ff92951deeacfc42b54deef0/unity/Tiled2Unity/Scripts/Editor/ImportTiled2Unity.Prefab.cs#L691-L717
sghanta commented 7 years ago

@Jazzepi Unity:isTrigger is working for other individual objects without me having to handle it, but for the large water polygon colliders, it isn't working for some reason. I'm trying to figure out if I have to do something special with the custom importer for colliders to make them work.

I confirmed that the custom importer is not running my class at all and I think, if I can figure out what is wrong with unity:isTrigger, that will also solve this problem.

sghanta commented 7 years ago

@Jazzepi I finally figured it out. Since the HandleCustomProperties function was not running for colliders, I searched for all the polygon colliders in the CustomizePrefab function and changed it to what I needed to do. Everything works exactly how I need it to now. Thanks for your help!

[Tiled2Unity.CustomTiledImporter]
public class CustomImporter_Objects : Tiled2Unity.ICustomTiledImporter
{

    public void HandleCustomProperties(GameObject gameObject, IDictionary<string, string> customProperties)
    {
        if (customProperties.ContainsKey("Terrain"))
        {
            InteractableTile tile = gameObject.AddComponent<InteractableTile>();
            tile.TileType = customProperties["Terrain"];
        }
    }

    public void CustomizePrefab(GameObject prefab)
    {
        var polygon2Ds = prefab.GetComponentsInChildren<PolygonCollider2D>();
        if (polygon2Ds == null)
        {
            return;
        }
        foreach(PolygonCollider2D comp in polygon2Ds)
        {
            if (comp.gameObject.name.Contains("Collision_waterfall"))
            {
                comp.isTrigger = true;
                TerrainController terrain = comp.gameObject.AddComponent<TerrainController>();
                terrain.waterFall = true;
            }
            else if (comp.gameObject.name.Contains("Collision_water"))
            {
                comp.isTrigger = true;
                TerrainController terrain = comp.gameObject.AddComponent<TerrainController>();
                terrain.water = true;
            }
            else if(comp.gameObject.name.Contains("Collision_sand"))
            {
                comp.isTrigger = true;
                TerrainController terrain = comp.gameObject.AddComponent<TerrainController>();
                terrain.sand = true;
            }
        }
    }
}
Jazzepi commented 7 years ago

Nice! Thanks for posting your solution.