Seanba / Tiled2Unity

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

Is there any way to get the customProperties of the map as a whole? #113

Closed anchpop closed 7 years ago

anchpop commented 7 years ago
[Tiled2Unity.CustomTiledImporter]
public class CustomImporter_TransitionTiles : Tiled2Unity.ICustomTiledImporter
{
    string markerTag = "TransitionMarker";
    public void HandleCustomProperties(GameObject gameObject,
        IDictionary<string, string> customProperties)
    {
        if (customProperties.ContainsKey("test"))
        {
              // Do something with customProperties
        }
    }

    public void CustomizePrefab(GameObject prefab)
    {
        // Do nothing, since we don't have access to customProperties!
    }
}

I'd like to be able to see the properties that can be defined in the Map > Map Properties menu, is there any way to do this?

image

Seanba commented 7 years ago

Hi there. The root GameObject of your prefab has a TiledMap component that contains all those properties ...

image

... you can access that component by using code like this ...

var tiledMap = gameObject.GetComponentInParent<Tiled2Unity.TiledMap>();

Hope that helps. -Sean

anchpop commented 7 years ago

Sorry Sean but I don't understand, I'm trying to figure out how to get access to this:

image

Also I think I forgot to mention but this is in a custom importer script.

Also, thanks for your amazing software! I don't know what my team would do without being able to use Tiled with Unity

Seanba commented 7 years ago

Oh, I see. No, we can't get the custom properties of everything all at once. We visit each group of custom properties on a per-object basis through the HandleCustomProperties method one at a time.

I'm guessing you have some dependencies on custom properties between different parts of your map? For that I would still use HandleCustomProperties and add temporary "data" components to your map objects as they are processed. Then, I would use the CustomizePrefab method to process the map as a whole, using those temporary components you added (and remove them when done).

I've done this sort of thing before and nice thing about it is you can have the functionality you need on methods on those temporary behaviors. It keeps this custom importer clean.

Here is some really rough code I'm bringing up from memory that has that basic idea:

[Tiled2Unity.CustomTiledImporter]
public class MyCustomImporter : Tiled2Unity.ICustomTiledImporter
{
    public void HandleCustomProperties(GameObject gameObject,
        IDictionary<string, string> customProperties)
    {
        var compiler = gameObject.AddComponent<MapCompiler>();
        compiler.Properties = customProperties;
    }

    public void CustomizePrefab(GameObject prefab)
    {
        foreach (var compiler in prefab.GetComponentsInChilder<MapCompilder>())
        {
            compiler.Compile(); // My custom method
            compiler.gameObject.Destroy(compiler); // Remove compiler. We are done with it.
        }
    }
}
anchpop commented 7 years ago

I'm sorry but I think you're still misunderstanding. I'm sure you know that just as tile objects can have custom properties, maps can too. Lets say I have two types of levels in my game, some space levels with no gravity, and some planet levels with varying amounts of gravity. It'd be nice if I could set a custom map property for the gravity scale and could then access it from the custom importer.

I apologize if I'm not explaining myself clearly! And thanks for all your help, by the way

Seanba commented 7 years ago

Okay, let's stick with that gravity example and see if I can figure it out.

So, say we've got a custom gravity value on the map in Tiled ... image

... now, what we'd like to do is have that gravity value imported into your Unity map, correct?

I'd start off by creating a new behaviour class that will store the gravity value:

using UnityEngine;

class MyGravity : MonoBeahviour
{
    public float Gravity = 0;
}

Then, here is how I'd author a custom importer that takes that gravity custom property from Tiled and shoves it into my map in Unity. Basically, we're going to add that MyGravity component to any object, exported from Tiled, that has the gravity custom property on it ...

[Tiled2Unity.CustomTiledImporter]
class MyCustomImporter : Tiled2Unity.ICustomTiledImporter
{

    public void HandleCustomProperties(UnityEngine.GameObject gameObject, IDictionary<string, string> props)
    {
        // Does this game object have a gravity custom property?
        // If so, we'll add a gravity component to it
        if (!props.ContainsKey("gravity"))
            return;

        // Get the gravity value from the property value string
        // (Use TryParse instead of Parse to get get input errors)
        float gravity = 0.0f;
        bool success = float.TryParse(props["gravity"], out gravity);
        if (!success)
        {
            Log.ErrorFormat("Gravity value misformed: {0}", props["gravity"]);
        }

        // Add a component to the game object that contains the gravity
        var comp = gameObject.AddComponent<MyGravity>();
        comp.Gravity = gravity;
    }

    public void CustomizePrefab(UnityEngine.GameObject prefab)
    {
        // Do nothing (at least yet)
    }
}

Is that along the path you're talking about?

anchpop commented 7 years ago

Hi Sean, sorry it took me so long to reply and thanks for your time :). That's exactly the answer I was looking for!

Seanba commented 7 years ago

Glad we got it figured out. Remember to keep custom importer scripts inside a folder named "Editor" otherwise they won't work. That's something that Unity requires that can be an easy mistake to make.