Search Unity

[RELEASED] Super Tilemap Editor

Discussion in 'Assets and Asset Store' started by CreativeSpore, Feb 21, 2016.

  1. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    You can put two different colliders with different tags in the same kind of tile if you create a gameobject with both colliders (maybe as children of this game object), create a prefab with it and attach the prefab to the tile you want.
    This way, the tile will instantiate the prefab adding the two colliders needed.
     
  2. LionelBarrancoT8

    LionelBarrancoT8

    Joined:
    Sep 21, 2016
    Posts:
    1
    Hello guys,

    Congratulation for your work on this plugin.
    We are a small team using it, it’s really powerfull!

    I got a suggestion to an option which could be useful for many game developers, I guess.
    In our game, we are already using few tilesMaps for some reasons.
    (My developer will hate me, if i had another one =p)
    So, I’m looking for optimized solution to got some diversity in our “Ground” tileMap.

    It would be realllly amazing if a brush (or something else) can merge 2 tiles regarding alpha of the tile.
    Like this (wonderfull) example.



    I hope this idea is clear enough, what do you think about it?
    It would be sooooo size saver and a huge time saver.
     
  3. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Hi there,
    I'm glad to know your team is enjoying using this tool ;)
    About your request, right now each tile in a tilemap contains a single tile.
    Technically a merge could be possible, but it's not trivial to achieve.
    I will take this request into account to be investigates. I think it could be really useful too.
     
    LionelBarrancoT8 likes this.
  4. Cookie966

    Cookie966

    Joined:
    Jun 24, 2015
    Posts:
    7
    I am planning on buying this within the next few days because it looks amazing! I did have one question though, and forgive me if it has been asked already.

    I have worked on 2D games in the past that had a false z plane (using the y coordinate to update the sorting layers so that anything with a lower y value would appear in front of an object with a higher y value as they moved in the scene). Since it appears that these tiles are placed on a single gameObject, is this still easily achievable through code? Or will I have to put anything that should be sorted manually into the scene and just use the tile editor for creating my backgrounds?
     
  5. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Hi there,

    The tiles are rendered using a MeshRenderer and a MeshFilter with the geometry.
    By the default, the MeshRenderer use the Sprites-Default material allowing you to sort by sorting axis and sorting order.
    But these settings are for all tiles, because all of them use the same MeshRenderer for performance reasons ( creating a gameobject per tile would be a performance killer for big tilemaps).
    But you have a work around for that. I guess you don't want to sort all the tiles but some of them, like a tree, high grass, post, etc.
    In that cases, you can create a gameobject with the component TileObjectBehaviour attached, create a prefab, and attach this prefab to the tiles you want to be created as a gameobject.
    This script will add a SpriteRenderer component and once instantiated by painting a tile with this prefab attached, the script will create a sprite looking like the tile.
    Now you can add to this prefab any other script to change the sorting order according to the Y position.
     
  6. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Unity 5.5 is here, and there is a small change you need to apply for this tool to be compatible, until the next release is published.
    "\Assets\CreativeSpore\SuperTilemapEditor\Scripts\Tilemap\Tilemap.cs(376):"
    #if UNITY_EDITOR && UNITY_5_4
    should be
    #if UNITY_EDITOR && (UNITY_5_4 || UNITY_5_5)
    Code (CSharp):
    1.         Material FindDefaultSpriteMaterial()
    2.         {
    3. #if UNITY_EDITOR && (UNITY_5_4 || UNITY_5_5)
    4.             return UnityEditor.AssetDatabase.GetBuiltinExtraResource<Material>("Sprites-Default.mat"); //fix: Unity 5.4.0f3 is not finding the material using Resources
    5. #else
    6.             return Resources.GetBuiltinResource<Material>("Sprites-Default.mat");
    7. #endif
    8.         }
     
    Last edited: Dec 4, 2016
  7. meapps

    meapps

    Joined:
    May 21, 2013
    Posts:
    167
    didnt fix it, reimported also tried it with an blank project.


    2016-12-04 11_13_12-Unity 5.5.0f3 Personal (64bit).png
     
  8. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    My bad :( It was UNITY_5_5 with upper case. I have edited the fix
     
  9. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    So I am looking for a tile manager for a top down 2D survival / crafting / adventure game that I want to build as this is one of the tools that is at the top of my list but I have a few questions about functionality I am looking for and what this library will provide. The core things I am looking to do are:

    1. Procedurally generating maps / "dungeons" that can be persisted in the game save file (the main map levels) or be one use maps (for stuff like "dungeons", a.k.a Diablo 3 Rifts / PoE Maps). (the "Run-Time tilemap generation with colliders" listed in the store makes me think the auto generation of maps is possible but how much of this functionality is built into the tool and how much would I have to learn to write myself and what about saving these maps to load again?)
    2. With part of this game being about crafting include building structures, planting crops, cutting down trees, mining rocks, etc., the maps need to be editable by the user (which is why being able to save the main map levels in a save file or such is critical).
    3. Be able to modified the map through code / events (for example, having a tree grow back after X amount of time after it was cut and such). (based on the documentation, seems like this is possible).
    4. Should be able to support animated tiles (for stuff like moving water, flower swaying, etc.) (this documentation mentioning the AnimBrush makes me think that is what this is for)
    5. Needs to be able to support very large maps so something smart enough to know it does not need render map tiles that are several screens away (ideally would like to be able to get into the 20 - 25 million tiles range per map).

    Any insight you can give me on these points would be awesome, thanks.
     
  10. Cookie966

    Cookie966

    Joined:
    Jun 24, 2015
    Posts:
    7
    Thanks! I'm looking into it now! Also, on your previous post, you might want to use UNITY_5_5_OR_NEWER so that it doesn't have to be updated with every Unity version.
     
    CreativeSpore likes this.
  11. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Hi there,
    I will ask below to your questions:
    1. About procedural maps. You can add a tile at any world position or grid position simply by calling SetTileData. To update the tilemap you need to call UpdateMesh, what should be called after editing all the tiles to improve the performance. So you don't need to specify the tilemap size and you can create it on the fly. About the colliders, they are automatically generated when you set a tile with colliders and the colliders are merged together to create a seamless collider segments, removing the segments enclosed inside the collision shape to save memory a useless calculations.
    I have attached the script for the Roguelike demo used to generate a random tilemap in real time.
    2. About saving the map in a file. There is no exportation script more than saving the map in the scene file. But all the data you need to save is stored in a single unsigned int, so all you need to do to store the tilemap data in a file is iterate through all the tiles using the tilemap property MinGridX, MinGridY, MaxGridX. MaxGridY and store the unsigned int retrieved by GetTileData for each grid position.
    3. As I said, you can modify the map in runtime.
    4. You can use the AnimBrush to created animations using the tiles as frames and also specify a different animation speed for each animation.
    5. You can see a more detailed explanation about how tilemaps works in the online manual, section 7: Advanced Topics. I think 20-25 million tiles are too much to be managed, but the tilemap edition has been improved a lot to allow big tilemaps with a good performance. It depends on the system, memory, etc, but you should get a good performance if you don't go for something crazy. In case of open worlds, with large areas, you need to use a streaming manager to basically generate the world around the player. I have attached another script used to generate a procedural tilemap around a gameobject, that could be the camera. It's called RoguelikeStreamingSource.

    If you have more questions, don't hesitate to ask.
     

    Attached Files:

  12. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Thanks for the tip ;) I will add this tag in the code for the next version.
     
  13. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    Thanks for the information, I will take a look at the attached scripts and let you know if I have any more questions.
     
  14. LarryWP

    LarryWP

    Joined:
    Oct 31, 2014
    Posts:
    57
    I'm trying to import a tmx file saved in xml layer format. Going by the video tutorial for this, I do the same, but I keep getting a magenta square instead of my tiled map. The tilesets look fine. I have tried a ton of different things, but it keeps coming up magenta. I know that magenta is used for some transparencies. It also says in a console error "the Default.mat could not be loaded from the resource file."

    EDIT: I read up above and made the change to the Tilemap.cs file and now some of the TMX tiles import, but most are a weird white. I can paint with the tiles inside Unity now, but the import of the TMX sucks.

    I'm stuck...
     
    Last edited: Dec 9, 2016
  15. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    I hope the next week the new version of Super Tilemap Editor is released with support for UNITY 5.5 and more painting features. But right now you have to apply the small fix above, you already did.

    About TMX, not everything is supported right now, only importing tiles and tilesets, but not tile objects, for example.
    If you can send me by email your tmx file, I will check what is going on.
     
  16. LarryWP

    LarryWP

    Joined:
    Oct 31, 2014
    Posts:
    57
    It's sent. I have no objects or anything special other than just tiles. Thanks.

    Is there any information that I may have missed that this product does not support Tiled objects? I never saw this before now.

    EDIT: I downloaded Tiled2Unity for FREE at this site and it imports perfectly and simple, AND it is updated for Unity 5.5:
    https://seanba.itch.io/tiled2unity/download/eyJleHBpcmVzIjoxNDgxMzA0NzU2LCJpZCI6NTk4MDh9.orWbPItH4gt7peiH30RrejQvy10=

    EDIT2: This is two days later and Juan (CreativeSpore) found objects in my map. I have no idea how they got there but they are there. I made another map and it has no object layers, and it loads fine. Actually it loads more than fine. Easy! Thanks Juan, it was my fault.
     
    Last edited: Dec 10, 2016
  17. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Is reading tile data expensive?

    I want to check the tile type as the player move, so it will be doing the following for every frame the player moves.
    If it is expensive or not efficient, is there a better way to check tile data every frame?

    Code (csharp):
    1.  
    2. public bool IsTile (int x, int y, Tilemap map, string tile = "") {
    3.  uint rawTileData = map.GetTileData(x, y);
    4.  tileData.SetData(rawTileData);
    5.  int tileId = tileData.tileId;
    6.  if (tileId == 65535) {
    7.  return false;
    8.  }
    9.  if (tile != "") {
    10.  return map.Tileset.Tiles [tileId].paramContainer.GetBoolParam (tile);
    11.  }
    12.  
    13.  return false;
    14.  }
    15. [code]
     
  18. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Hi there,
    The class TileData was created to be a helper class. It's not going to be a bottle neck if you use that code, but to make it even more efficient you could avoid using the TileData:
    Code (CSharp):
    1. public bool IsTile(int x, int y, Tilemap map, string tile = "")
    2. {
    3.     uint rawTileData = map.GetTileData(x, y);
    4.     int tileId = Tileset.GetTileIdFromTileData(rawTileData);
    5.     Tile tileObj = map.Tileset.GetTile(tileId);
    6.     if (tileObj != null && tile != "")
    7.     {
    8.         return tileObj.paramContainer.GetBoolParam(tile);
    9.     }
    10.  
    11.     return false;
    12. }
    13.  
    14. public bool IsTile(Vector3 position, Tilemap map, string tile = "")
    15. {
    16.     //InverseTransformPoint returns the position relative to the tilemap, not needed if tilemap position is (0,0,0)
    17.     uint rawTileData = map.GetTileData(map.transform.InverseTransformPoint(position));
    18.     int tileId = Tileset.GetTileIdFromTileData(rawTileData);
    19.     Tile tileObj = map.Tileset.GetTile(tileId);
    20.     if (tileObj != null && tile != "")
    21.     {
    22.         return tileObj.paramContainer.GetBoolParam(tile);
    23.     }
    24.  
    25.     return false;
    26. }
    27.  
    I have included a second version using a world position.
     
  19. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Thanks! Will use position instead of x/y
     
  20. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    There is also a real annoying bug with Tile Properties -> Parameters list.

    When ever I add a new parameter and try to edit the name by double click and then move the cursor, the selection unhighlights.

    I am using unity 5.3.4.1 (osx).
     
  21. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore So I decided to go with your library but have some bad and good news. The bad news is that I immediately ran into an issue with an error about loading the Sprite-Default.mat which seemed to cause my issue with all tiles being "painted" as pink.

    The good news is that even though it look me at little (probably should have just started with looking at the code instead of trying to google), I found the issue and it has to do with the FindDefaultSpriteMaterial() method in the Tilemap.cs file. If I change UNITY_5_4 to UNITY_5_4_OR_NEWER in that method (starting at line 374):

    Code (CSharp):
    1. Material FindDefaultSpriteMaterial()
    2. {
    3. #if UNITY_EDITOR && UNITY_5_4_OR_NEWER
    4.             return UnityEditor.AssetDatabase.GetBuiltinExtraResource<Material>("Sprites-Default.mat"); //fix: Unity 5.4.0f3 is not finding the material using Resources
    5. #else
    6.             return Resources.GetBuiltinResource<Material>("Sprites-Default.mat");
    7. #endif
    8. }
    That got rid of the error for me (though there are other warnings that you probably want to clean up at some point) and painting starting to work properly, I'm using 5.5.0f3.

    As this is not a great first experience with this library, I would suggest you try to get a fix submitted to the asset store for review for this issue.
     
  22. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    Also just now noticed your post a few above mine so I guess you already know.
     
  23. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    I will fix this for next release.
    You can manually fix this issue by changing this line:
    "\Assets\CreativeSpore\SuperTilemapEditor\Scripts\Tilemap\Editor\TilePropertiesControl.cs(202):"
    Code (CSharp):
    1. if (e.isMouse && !rList.Contains(e.mousePosition))
    For this one:
    Code (CSharp):
    1. if (e.type == EventType.MouseDown && !rList.Contains(e.mousePosition))
     
    mrm83 likes this.
  24. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Sorry for the issue. I posted the fix but it has been moved too far because of the recent posts.
    This is fixed for next release I hope will be available during the next week.
    The new code looks like this:
    Code (CSharp):
    1. Material FindDefaultSpriteMaterial()
    2.         {
    3. #if UNITY_EDITOR && (UNITY_5_4 || UNITY_5_5_OR_NEWER)
    4.             return UnityEditor.AssetDatabase.GetBuiltinExtraResource<Material>("Sprites-Default.mat"); //fix: Unity 5.4.0f3 is not finding the material using Resources
    5. #else
    6.             return Resources.GetBuiltinResource<Material>("Sprites-Default.mat");
    7. #endif
    8.         }
    9.  
     
  25. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore So this is a weirdness that I understand why it is happening so just looking for guidance on how to accomplish what I am looking for as I would think it would be possible.

    So I created a carpet brush for dirt with a grass edge and one for water with a dirt edge. What I am looking to do is have an area of grass, inside that an area of dirt, and inside that an area of water however this is the result:

    Screen Shot 2016-12-11 at 3.09.48 PM.png

    Now I understand what this it happening, the 4 interior conners for the dirt brush have grass in the middle of the 4 items which seems to make the edges on an angle look correct but also adds grass where the water with dirt edges are which is not what I am looking for.

    Is there a way to accomplish what I am looking for (with the water inside the dirt not having any grass around it) with the use of carpet brushes (as without them, this becomes a very tedious task)?
     
  26. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    Nevermind, found the tile / brush id version in the API docs.

    @CreativeSpore Another question I have is about you rogue map generation code. I am a little confused about this code:

    Code (CSharp):
    1. uint tileWater = (8 << 16);
    2. uint tileWaterPlants = (24 << 16);
    3. uint tileDarkGrass = 66;
    4. uint tileGrass = (9 << 16);
    5. uint tileFlowers = (22 << 16);
    6. uint tileMountains = (23 << 16);
    The confusing part is how those values equate to the tile that are going to be render and therefore not quite sure how to modify that part to work with my tileset.
     
    Last edited: Dec 12, 2016
  27. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore Ok, so running into some confusion about how to detect a collision on single tiles.

    So I have a tilemap group with 4 different tilemaps right now and one of them is a destructible one where destructible tiles are. I searched the UI, manual, and this thread and while I saw places that said you could tell a tile to have its own collider instead of connecting them (which I need this case to destroy tiles one by one), I could find find how to do that. The other issue is that the only documentation I could find was detecting collisions one the tilemap, not tiles. I added a prefab to the tiles in question but don't see if / how to access its collider from script on the prefab attached to the tile.

    Is there any way to be able to detect a collision on a tile in a script that is attached to the tiles prefab?
     
  28. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    To achieve this you can change the Autotiling Mode of the water/Dirt Carpet brush to autotile with other tiles:
    upload_2016-12-12_14-2-48.png
    If you want to make it better, you can create a new Autotiling Group, instead of using the Deafault group, and check Group instead.
    To create a new group you have to select the tileset, go to the BrushGroups tab and add a new name for a group.
    upload_2016-12-12_14-5-16.png
    You can see an example of group in the RoguelikeTileset used for the garden carpet brush.
     
  29. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Just in case other person is looking for an answer, I will explain this:
    uint tileWater = (8 << 16);
    This is creating a tile data using the brush id 8. The tile data is a raw data stored in an unsigned int of 32bits including the tile flags, the brush id and the tile id. The brush is used when the tile id is chosen by brush during the refresh of a tilemap.
    The tile flags are placed in the first 4 bits, the brush id in the next 12 bits, and the tile id in the last 16 bits.
    So to create a tile data with no flags and no brush you can do this:
    uint tileData = tileId; // tileId in an integer with the id of the tile
    But to set a brush you need to move the data 16 bits to the left, so to set the brush id 9 in a tile data you need to add << 16:
    uint tileData = 9 << 16; // or uint tileData = brushId << 16;
     
  30. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    The colliders for all the tiles in a tilemap are merged together so when you get an OnCollision event, you really collide with a tilemapChunk. A tilemap chunk is an invisible gameObject, children of the tilemap with the information of a chunk of tiles (60x60) tiles. You can see the chunks in the editor limited by a red line.

    So when you receive a collision event, you can get the tile using the Collision event data:
    Code (CSharp):
    1. void OnCollisionEnter(Collision other)
    2. {
    3.   Vector3 tilePosition =  transform.position - other.impulse; // subtracting the impulse applied to resolve the collision, tilePosition should be the position inside the tile.
    4.   Tilemap tilemap = other.gameObject.GetComponentInParent<Tilemap>(); // this will take the tilemap involved in the collision
    5.   if(tilemap)
    6.   {
    7.     uint tileData = tilemap.GetTileData(tilePosition);
    8.     int tileId = Tileset.GetTileIdFromTileData(tileData);
    9.     int brushId = Tileset.GetBrushIdFromTileData(tileData);
    10.     Tile tile = tilemap.Tileset.GetTile(tileId);
    11.   }
    12. }
    13.  
    You can remove the tile by calling
    Code (CSharp):
    1.  
    2. tilemap.Erase(tilePosition);
    3. tilemap.UpdateMesh();
    4.  
     
    Shilo likes this.
  31. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore Thanks for the information. The bit shifting now make sense (though I will stick too to tile id for now as it is a bit more straight forward). I tried teh auto tiling mode a bit and it was not working out but I need to spend a bit more time trying to play with that and try groups too before I bug you about that again.

    On the collision stuff, there are 2 things that are different in my setup where your code example is not going to work.

    First I am working with the 2D collision system instead of the 3D one. I prefer to use this as all of my other code uses it and even though the APIs are similar, it does not seem like I can just switch to the 3D version without issues I am also assume the 2D physics engine to optimized to 2D which is the only type of physics I am going to need for this game).

    The other issue is that one of the colliders is a trigger collider (the weapon) as I want it to pass through the stone / tree / etc. when swinging which means that I don't think I have access to the collision (maybe there is some way that I just don't know).

    So is there any way to get a tile that had the collision with a 2d trigger based collider?
     
  32. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    My example was for a 3D collision event, but it's also valid for a 2D collision event.
    You can change the collider type to 2D (Edge or Polygon) and 3D (using a MeshCollider).
    upload_2016-12-13_15-46-1.png
    If the collider is a trigger, you will have to change the event for a OnTriggerEnter2D event.
    In this case, you don't need to subtract the impulse value from the transform.position.
    Code (CSharp):
    1.  
    2. void OnTriggerEnter2D(Collider2D other)
    3. {
    4.   Tilemap tilemap = other.gameObject.GetComponentInParent<Tilemap>(); // this will take the tilemap involved in the collision
    5.   if(tilemap)
    6.   {
    7.     uint tileData = tilemap.GetTileData(transform.position);
    8.     int tileId = Tileset.GetTileIdFromTileData(tileData);
    9.     int brushId = Tileset.GetBrushIdFromTileData(tileData);
    10.     Tile tile = tilemap.Tileset.GetTile(tileId);
    11.   }
    12. }
     
  33. Toscano_ca

    Toscano_ca

    Joined:
    Aug 6, 2016
    Posts:
    1
    Hello,
    is there a way to add custom material to a specific tile.
    Right now all tiles share the same material as sprite default that it is global in Tilemap.
    Thank you
     
  34. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore Ok so I have gotten close to getting the collision stuff to work but still not there. The issue that I am running into I have the onTriggerEnter2D on a weapon script attached the the bone looking game object in the screenshot below and when that hits the stone and that value of transform.position is always off by between 0.1 and 1 depending on where the bone looking thing is in relationship to the the stone. I have tried to look at different properties (like transform.up, transform.right, transform.localPosition, renderer.bounds, and a few others) but none of them would allow me to perform a consistent calculation that would give me the correct x / y values.

     
  35. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Right now you can only change the Physic material for all the tilemap colliders. You can create different tilemaps for each type of collider though.
    It could be possible in a future version, by grouping the colliders by physic material.
    Another option would be create a prefab with the TileObjectBehaviour attached and attach the prefan to a tile using the Tile Property Window. The TileObjectBehaviour will replicate the tile used to instantiate the prefab and you can add a custom collider to the prefab with a physic material.
     
  36. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    I would do this in a different way, by checking the position of a point in the bone. Let say the local position of the top of the bone is (0, 0.1) when the bone is not rotated. So you know the world position of the top of the bone using this code:
    Code (CSharp):
    1. Vector3 bonePos = bone.transform.TransformPoint( new (0f, .1f) );
    Whit this position you can check if there is a rock tile to destroy it.
    If you still want to use a collider for the bone to check if it collides the rock, you can still use this code to know, at the moment of the collision, if the top of the bone is over the rock tile. In this case you need to use the OnTriggerStay2D to check every frame where the bone is colliding the tilemap.

    A trick for the bone offset:
    You can add this to the bone script to display the offset position:
    Code (CSharp):
    1.  
    2. public Vector2 Offset;
    3. void OnDrawGizmosSelected()
    4. {
    5.   Gizmos.DrawSphere(transform.TransformPoint(Offset), 0.01f);
    6. }
     
  37. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Is there a way to optimize meshupdate()?

    When I change a tile from code and meshUpdate calls, it generates 1.2MB of GC!
    I can't have this GC as the game is for mobile.

    Is live updating of tilemap heavy? My map is only 180x180 (9 chunks)
    I tried reducing it to 60x60 and it still does the same amount of GCallocation!

    I tried reducing chuckSize to 8 but it still allocs a whoooping 60kb gc =(
     
    Last edited: Dec 14, 2016
  38. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    This is going to be improved in next version.
    When you call UpdateMesh, the mesh is updated only for the modified chunks, so probably that is the reason no matter what size you tilemap is, you always get the same GC when you change a tile.
    Some of the modifications made were:
    Change the m_vertices, m_uvs, and m_triangles in the class TilemapChunk static:
    upload_2016-12-15_12-9-55.png
    Adding static between private and List will make the trick.
    Also, from Unity 5.2 an above, you can call SetVertices, SetTriangles and SetUVs to update the mesh, instead of calling ToArray() for each of the List members.
    upload_2016-12-15_12-12-50.png

    If you find important issues while developing your game and cannot wait, let me know and I will send you a patch.
     
  39. meapps

    meapps

    Joined:
    May 21, 2013
    Posts:
    167
    @ryanzec you can also use for most of the Collison etc... Prefabs its maybe easier then...
    But my game is turnbase i use tweens for the movement.

    Master of Potions Unity Screenshot.png
     
    CreativeSpore likes this.
  40. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Yeah, those toArrays were contributing to half the GCs I was seeing.

    Also, would it be possible for the asset to ditch linq? Linq is pretty bad for mobile with all those gc allocations..
    I've updated a few in the source myself, but then it gets wiped every time i update.
     
  41. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Yes, you are right. All linq queries has been removed as well.
     
    mrm83 likes this.
  42. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @meapps / @CreativeSpore So if I have a prefabs for these tiles (and any tiles that I am going to want to have this type of interaction with is going to need a prefab anyways), then instead of using colliders on the tilemaps / tiles, I could just add the Collider2D to the prefab and then that collider should just act as if I manually placed the tiles myself?

    If that is so I will probably try that approach once I have a chance to give @CreativeSpore's latest suggestions a try.
     
  43. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Yes, you could do that, but it's less efficient to create a gameobject per each tile than using the tilemap generated colliders for all of them. You you should use it only for special objects.
    For example I use prefabs for tiles that will have an special behaviour, like breakable crates, chest, a door, etc, but not for other non interactable objects like furniture, walls, trees, etc.
     
  44. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Question about brushes..

    my tile size is 16x16. I have a tree that is 16x32
    the top 16x16 are the leaves, the bottom 16x16 is the trunk

    Is it possible to create a brush that has 2 tiles or link them together somehow? I want to be able to create a brush that can draw the tree.
    ie: if i select the tree brush, it will draw the bottom tile at x,y and then the leaves part at x,y+1
     
  45. Padilha

    Padilha

    Joined:
    Jun 6, 2016
    Posts:
    12
    I'm trying to put a tileset with irregular size, example:

    The tileset of my map is the size of 140x2172;
    In the Tiled Map Editor it only considers the tile if it is divided by the size of the tile placed in the property.

    Let's assume I've placed the size of my tile 16x16 on my tileset.

    Then 140/16 = 8.75;

    Let's consider 16 * 8 = 128

    140 - 128 = 12, then it will not consider those 12 in the tileset formation

    Am I doing something wrong, or did I forget to set some parameters?
     
  46. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    You can attach a prefab with the tree to a tile, using the tile property window.
    In the next version (pending of approval and maybe available during the next week ) if a tile has a prefab attached, the prefab preview will be displayed instead of the tile in the tile palette. Right now you would need to create a tile looking like an icon of the prefab.
    If you want to show the prefab preview before the next version is released, here is the modified version of the method DoGuiDrawTileFromTiledata located in TilesetEditor.cs:
    Code (CSharp):
    1. public static void DoGUIDrawTileFromTileData(Rect dstRect, uint tileData, Tileset tileset, Rect customUV = default(Rect))
    2. {
    3.     int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId);
    4.     Tile tile = tileset.GetTile(tileId);
    5.     if (tileId != Tileset.k_TileId_Empty && tileset.AtlasTexture)
    6.     {
    7.         if ((tileData & Tileset.k_TileFlag_FlipV) != 0) GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), dstRect.center);
    8.         if ((tileData & Tileset.k_TileFlag_FlipH) != 0) GUIUtility.ScaleAroundPivot(new Vector2(-1f, 1f), dstRect.center);
    9.         if ((tileData & Tileset.k_TileFlag_Rot90) != 0) GUIUtility.RotateAroundPivot(90f, dstRect.center);
    10.         if (tile != null && tile.prefabData.prefab)
    11.         {
    12.             Texture2D assetPreview = AssetPreview.GetAssetPreview(tile.prefabData.prefab);
    13.             if (assetPreview)
    14.                 GUI.DrawTexture(dstRect, assetPreview, ScaleMode.ScaleToFit);                      
    15.             else
    16.                 GUI.DrawTextureWithTexCoords(dstRect, tileset.AtlasTexture, customUV == default(Rect) && tile != null ? tile.uv : customUV, true);
    17.         }
    18.         else
    19.         {
    20.             GUI.DrawTextureWithTexCoords(dstRect, tileset.AtlasTexture, customUV == default(Rect) && tile != null ? tile.uv : customUV, true);
    21.         }
    22.         GUI.matrix = Matrix4x4.identity;
    23.     }
    24. }
    25.  
     
  47. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,192
    Exactly, when you press Slice in the tileset, the atlas texture will be sliced in multiples of tile size. So the last 12 pixels won't be considered,
     
  48. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    I am already attaching a prefab, but the thing is.. I have 1000+ trees.. that is 1000+ objects instantiated. Would be awesome if the tilemap can do this without using a prefab.
     
  49. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore @meapps Ok, so I decided to go with the prefab approach, at least for now, thanks for all the help.

    Another question is whether or not it is possible to be able to get the sprite renderer for a tile with the tileId?

    Also a suggestion, when building maps manually, the middle mouse button does not work with a trackpad as there is no middle mouse button gesture so something else (like holding alt / option) woul dbe great.
     
  50. Padilha

    Padilha

    Joined:
    Jun 6, 2016
    Posts:
    12
    When I press the Slice button, this does not happen