Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[RELEASED] Super Tilemap Editor

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

  1. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore So I am noticed a weird issue with the latest version (I am also using your patch version for getting prefab instance however I am seeing this issue without it on 1.4.7). I have a tile that has a prefab with has a TileObjectBehaviour script with the Changed Sprite Only checked. The weird things is that the tile shown up fine in the scene window:

    Screen Shot 2018-01-08 at 6.14.27 PM.png

    How it does not render in the game window and I am not sure why:

    Screen Shot 2018-01-08 at 6.14.50 PM.png
     
  2. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    I mean, it IS useful to be able to have in the scene view. I just need a way to turn it on and off scenewide so I can setup all my room's with parallaxing as needed, then turn it all off so I can focus my work on other design elements in the rooms after I'm done with parallaxing work.
     
  3. CreativeSpore

    CreativeSpore

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

    Good to know you liked the tutorial. I hope the second part is available soon.
    About your question, I think the way you check for the tilemap is fine. But if it doesn't work as expected let me know.
    In my case, I've just check if there is a collision and the collision in the code for the next part of the tutorial:
    Code (CSharp):
    1. protected bool CanMove(Vector2 dir)
    2.         {
    3.             bool canMove;
    4.             bool savedValue = Physics2D.queriesHitTriggers;
    5.             Physics2D.queriesHitTriggers = false;
    6.             if (!Physics2D.Raycast(transform.position, dir, dir.magnitude))
    7.             {
    8.                 Debug.DrawRay(m_movingPointA, dir, Color.green * 0.4f, 1f);
    9.                 canMove = true;
    10.             }
    11.             else
    12.             {
    13.                 Debug.DrawRay(m_movingPointA, dir, Color.red * 0.4f, 1f);
    14.                 canMove = false;
    15.             }
    16.             Physics2D.queriesHitTriggers = savedValue;
    17.             return canMove;
    18.         }
    This is checking if there is a collision from the player position to the destination (dir vector) and questHitTriggers is set to false to avoid colliding with the player collider. But there are many ways to achieve the same.
     
  4. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    I will see if I can add a switch to disable the parallax in the SceneView.
    Right now, you can add this line to the STETilemap code to avoid applying the parallax if the camera is the SceneView Camera:
    upload_2018-1-9_18-50-58.png
     
  5. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    This is usually happening when you use sprites (and tilemaps) with the same sorting layer, sorting order and Z position.
    The problem is caused by Z fighting, when two or more graphics are rendered with the same order.
     
  6. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    Arg... I though it was a sort layer / order in layer but that all checked out fine but for some reason objects seem to randomly have there z value change from time to time and did not think to look at that but that was the issue.

    Thanks for the great support as always.
     
    CreativeSpore likes this.
  7. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    Awesome, many thanks!
     
    CreativeSpore likes this.
  8. ThrakaAndy

    ThrakaAndy

    Joined:
    Nov 21, 2013
    Posts:
    3
    Merging both of our ideas, I came up with this. It uses the collider on the player to cast (avoiding self collision) and it also uses a contact filter which (by default) avoids triggers. The deadResults variable is just a [1] dimension array already allocated so as to say "I dont care what I hit." It also only checks the cell next to you (scale with cellsize)

    Code (CSharp):
    1.  
    2. bool CanMove(Vector2 direction)
    3. {
    4.     Vector2 distance = direction;
    5.     distance.Scale(cellSize);
    6.  
    7.     if (Collider.Raycast(direction, contactFilter, deadResults, distance.magnitude) > 0)
    8.     {
    9.         Debug.DrawRay(transform.position, distance, Color.red * 0.4f);
    10.         return false;
    11.     }
    12.     else
    13.     {
    14.         Debug.DrawRay(transform.position, distance, Color.green * 0.4f);
    15.         return true;
    16.     }
    17. }
    18.  
     
    CreativeSpore likes this.
  9. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore So I have a possible suggesting if you think it might be useful.

    The use case for this suggestion is I have a game that allows for the user to build stuff in the world. I also want the building of the these tiles to have multiple stages that can display different sprites at each stage. Most of the functionality for this can be handled with giving the first staged sprite a prefab that has the staged build script on it (which also stores all the stages data). The issue (or more so inconvenience) I ran into it that I wanted to be able to reference the different stages sprite's just by the TileId however I did not find anything pre-built in the library to allow me to get a tile's sprite by TileId (maybe I missed it).

    My suggestion is to add a utility function that takes in a Tileset and a TileId and it returns the sprite that it references. What I did to accomplish this was to reverse engineer the TileObjectBehaviour.GetOrCreateSprite() method into a more generic version:

    Code (CSharp):
    1. using System;
    2. using CreativeSpore.SuperTilemapEditor;
    3. using UnityEngine;
    4.  
    5. namespace Game {
    6.   public static class CustomTilemapUtility {
    7.     // @todo: memoization?
    8.     public static Sprite GetTilesetSprite(STETilemap tilemap, int tileId) {
    9.       Tile tile = tilemap.Tileset.GetTile(tileId);
    10.  
    11.       if (tile == null) {
    12.         throw new Exception("tile was not found");
    13.       }
    14.  
    15.       float pixelsPerUnit = tilemap.Tileset.TilePxSize.x / tilemap.CellSize.x;
    16.       Vector2 atlasSize = new Vector2(tilemap.Tileset.AtlasTexture.width, tilemap.Tileset.AtlasTexture.height);
    17.       Rect spriteUv = new Rect(Vector2.Scale(tile.uv.position, atlasSize), Vector2.Scale(tile.uv.size, atlasSize));
    18.  
    19.       return Sprite.Create(tilemap.Tileset.AtlasTexture, spriteUv, new Vector2(.5f, .5f), pixelsPerUnit);
    20.     }
    21.   }
    22. }
    I figured I would just mention this incase you think this would be useful to be in the library itself. If not no worries, I can always just use this method I created.

    Also, if you think there is a better way to accomplish my use case that does not required what I am doing, I would be interested in hearing that.
     
    CreativeSpore likes this.
  10. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Thanks for sharing your code. I have decided to add a method in TilemapUtils to create a sprite from a tile and also use the sprite cache (to create the same sprite only once and save memory):
    Code (CSharp):
    1. private static Dictionary<string, Sprite> s_spriteCache = new Dictionary<string, Sprite>();
    2. public static Sprite GetOrCreateTileSprite(Tileset tileset, int tileId, float pixelsPerUnit = 0)
    3. {
    4.     Sprite sprite = null;
    5.     if(pixelsPerUnit <= 0)
    6.         pixelsPerUnit = tileset.PixelsPerUnit;
    7.     Tile tile = tileset.GetTile(tileId);
    8.     if (tile != null)
    9.     {
    10.         Vector2 atlasSize = new Vector2(tileset.AtlasTexture.width, tileset.AtlasTexture.height);
    11.         Rect spriteUV = new Rect(Vector2.Scale(tile.uv.position, atlasSize), Vector2.Scale(tile.uv.size, atlasSize));
    12.         string spriteName = tileset.name + "_" + tileId + "_" + pixelsPerUnit;
    13.         if (!s_spriteCache.TryGetValue(spriteName, out sprite) || !sprite)
    14.         {
    15.             sprite = Sprite.Create(tileset.AtlasTexture, spriteUV, new Vector2(.5f, .5f), pixelsPerUnit);
    16.             sprite.name = spriteName;
    17.             s_spriteCache[spriteName] = sprite;
    18.         }
    19.     }
    20.     return sprite;
    21. }
    22.  
    I have attached the new TilemapUtils class to this post.
     

    Attached Files:

  11. ThrakaAndy

    ThrakaAndy

    Joined:
    Nov 21, 2013
    Posts:
    3
    I can't seem to use the unity animator and state controller stuff with my prefabs generated by the tile placement. Once the animator changes the sprite frame of the prefab, it's automatically using a world scale of 1:1 (per pixel) and the sprite is no longer centered to the tilemap.

    How do I fix this?

    Thanks!
     
  12. CreativeSpore

    CreativeSpore

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

    I've been checking the code but there is nothing that change the prefab instance scale or position. Could it be related with the animation? Maybe because the instance is child of another gameObject?
    About the scale I am not sure why is happening, unless you Refresh the tilemap with the parameter refreshTileObjects to true.
    But the sprite displacement could be caused because the sprite you are changing has not centered pivot.
     
  13. Khena_B

    Khena_B

    Joined:
    Aug 21, 2014
    Posts:
    273
    Hey,

    Is it possible to have both edge colliders and polygon collider triggers on a single tilemap?

    Also is it possible to have a different tag/layer for each tiles?

    Thanks.
     
    Last edited: Jan 16, 2018
  14. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Hi!

    You can't have both colliders in a tilemap, unless you create the tiles as a gameObject using the TileObjectBehaviour component.

    It's the same with the tag/layer. You can create the tile as a gameObject to set the tag and layer.
     
    Woofo and Khena_B like this.
  15. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    I have fixed the warnings in the next update. Use the attached patch if you want to fix it now.
     

    Attached Files:

  16. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore So I am not sure if this is a bug or something I am not setting up right.

    I was testing out a feature of my game and found that I was unable to move when I should have been able to.

    Here is a screenshot of my map when I was unable to move to either square above or below the player:
    Screen Shot 2018-01-26 at 5.50.44 PM.png
    But if I remove an additional tile at the top or bottom, like this:
    Screen Shot 2018-01-26 at 5.50.25 PM.png
    I am able to move in all the green squares. All of the bricks have full colliders (I tried with polygon colliders and a few different map collider settings all with the same results).

    This is a turn based game so I am not using physics to move my character. The way the movement code works is that is does a raycast through the middle of the tile that I am looking to move towards and checks to see if it hit a collider that is attached to the tilemap. For example if the tile above the player has it bottom left corner located at 100 x 100, the raycast happens at 100.5 x 100.5 (each tile is 1 unity unit). I have checked the raycast code and that is working fine but with only one empty tile above and below the player, the raycast is hitting the map. I am not sure why this is happening or why if I remove an additional tile above or below the already empty tiles, the raycast no longer hit the map collider on any of the empty tiles.

    This also seems to happen in other weird cases and I can't really pinpoint the exact cause, for example, I can't move anywhere in this map:
    Screen Shot 2018-01-26 at 6.07.14 PM.png
    But I have not problem moving in this map:
    Screen Shot 2018-01-26 at 6.07.27 PM.png

    Any help with this would be great.
     
  17. Seiraniel

    Seiraniel

    Joined:
    Dec 23, 2014
    Posts:
    13
    Hi. I don't know if it is an issue with Super Tilemap Editor but I have had it for quite some time and tried many things to get rid of it.

    I have the tileset sheet set to clamp but I still get this visual artifact on sloped tiles.

    It flickers when the camera is moving around the scene. Sometimes it stays there and sometimes it disappears.

    artifact.png

    I'm using Unity 2017.3 and the latest version of Super Tilemap Editor.

    Thanks!
     
  18. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Hi there,
    I am not sure why it is not working but it should work fine. I don't see any collider lines in the screenshot, maybe you missed to enable the colliders in the tilemap. I recommend you to use edger colliders if you are using 2D colliders:
    upload_2018-1-29_10-2-59.png
     
  19. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    There some tips to get rid of the seams in the F.A.Q section of the manual.
    The best way to get rid of them completely is using extrusion, but sometimes it doesn't like because it deforms the tiles in the atlas.
    Other options are, using a pixel perfect camera to snap the camera position to the current pixel size. (I have attached the script of the camera I am using in one of the tutorials in case it helps you)
    The other option is adding some inner padding to the tiles. It cuts the tile border a little. Use a value between 0.2 and 0.4.
    Or enable pixel perfect.But I found this causing transparent seams in some cases.
    upload_2018-1-29_10-9-30.png
     

    Attached Files:

  20. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    @CreativeSpore Well the thing is that I am not using colliders for movement, at least not with physics (since this is a turn based game, that seems like a waste of performance). I am using a raycast in the middle of the tile I am looking to move to (so 100.5 x 100.5 if I want to move to 100 x 100) and I check to see if a collider that belongs to the map is there and then I either move if not or don't if there is one is there. Because of how this works, using an edge collider won't work as I am able to move anywhere if I use that (since the colliders are only on the edges).

    Eventually I might not even use colliders at all in movement, with it being a turn based game, I can actually manage it manually relative easy however I will still need collider for enemy / npc path finding to work and the current library I am using for that also requires polygon collider, edge ones does work (the path finding will go through walls). That might be something I can fix by configuring but maybe not and I know polygon colliders do work.

    One other question I have is about managing meta data for tiles. I am building and rogue like game (something like CDDA) and all the tiles are going to have a number of piece of meta data such as name, is it destructible (and health if so), can it burn (and how much damage it takes per turn burning), is it harmful to characters (like lava, poison, etc) and how much damage it does per turn, etc. I have been managing this data as parameters on the tiles which is working well from a coding stand point and reference data in Unity but managing that data in Unity is a bit tedious. Now one thing I though was I could have a separate JSON file that stores this data and just map it by the tile id but then being able to quickly related which tile has what data is not as easy. Is there any easy way to mass populate tile parameter data from a json file or something that does not required 1 by 1 entry?
     
  21. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    I see. In the tutorial I am working on, I use raycasting to check if a tile is passable but I throw the ray from actor position to target position.
    If dir is the moving vector, this is the method I use:
    Code (CSharp):
    1. protected bool CanMove(Vector2 dir)
    2. {
    3.     bool canMove;
    4.     bool savedValue = Physics2D.queriesHitTriggers;
    5.     Physics2D.queriesHitTriggers = false;
    6.     if (!Physics2D.Raycast(transform.position, dir, dir.magnitude))
    7.     {
    8.         Debug.DrawRay(m_movingPointA, dir, Color.green * 0.4f, 1f);
    9.         canMove = true;
    10.     }
    11.     else
    12.     {
    13.         Debug.DrawRay(m_movingPointA, dir, Color.red * 0.4f, 1f);
    14.         canMove = false;
    15.     }
    16.     Physics2D.queriesHitTriggers = savedValue;
    17.     return canMove;
    18. }
    But there is also a faster way to check if a tile is passable by checking the colliderData of that tile. This code is found in the included file "\CreativeSpore\SuperTilemapEditor\Extra\Tileset - Samples\Kenneys - Rogue Like\MapPathFinding\MapPathFinding.cs":
    Code (CSharp):
    1. public override bool IsPassable()
    2. {
    3.     bool isBlocked = false;
    4.     for (int i = 0; !isBlocked && i < m_tilemapGroup.Tilemaps.Count; ++i)
    5.     {
    6.         STETilemap tilemap = m_tilemapGroup[i];
    7.         if (tilemap && tilemap.ColliderType != eColliderType.None && tilemap.IsGridPositionInsideTilemap(GridX, GridY))
    8.         {
    9.             Tile tile = tilemap.GetTile(GridX, GridY);  [B]// or Tile tile = tilemap.GetTile(ray.origin);[/B]                  
    10.             isBlocked = tile != null && tile.collData.type != eTileCollider.None;                  
    11.         }
    12.     }
    13.     return !isBlocked;
    14. }
    15.  
    This is used in the MapTileNode class to define when a tilemap grid position is considered passable.
    Basically it is iterating trough all the tilemaps in a tilemap group to check if the grid position contains a tile with any collider on it.
    IsGridPositionInsideTilemap is used as an optimization but it is not needed.
    You can also use a world position, like ray.origin position instead of grid coordinates. For example:
    Tile tile = tilemap.GetTile(ray.origin);

    About your last question, it is something to be improved, but right now there is no other way to add parameters to the tiles.
    If this is useful, you can use MenuItem actions to add some parameters to the selected tiles or brushes in tileset:
    You need to place this code in a class in a file inside an Editor folder.
    Code (CSharp):
    1. [MenuItem("YourCustomActions/Set Selected Tiles as Grass")]
    2. private static void SetGrassTiles()
    3. {
    4.     Tileset selectedTileset = TilesetEditor.GetSelectedTileset();
    5.     if (selectedTileset && selectedTileset.TileSelection != null)
    6.     {
    7.         foreach (uint tileData in selectedTileset.TileSelection.selectionData)
    8.         {
    9.             Tile tile = selectedTileset.GetTile(Tileset.GetTileIdFromTileData(tileData));
    10.             if(tile != null)
    11.             {
    12.                 tile.paramContainer.SetParam("Type", 12);
    13.                 tile.paramContainer.SetParam("CustomFloatParam", 52.2f);
    14.                 tile.paramContainer.SetParam("CustomBoolParam", true);
    15.             }
    16.             else
    17.             {
    18.                 TilesetBrush brush = selectedTileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData));
    19.                 if(brush!=null)
    20.                 {
    21.                     brush.Params.SetParam("Type", 12);
    22.                     brush.Params.SetParam("CustomFloatParam", 52.2f);
    23.                     brush.Params.SetParam("CustomBoolParam", true);
    24.                 }
    25.             }
    26.         }
    27.     }
    28. }
    29.  
    Working on this I found the SetParam(string, string) missing. I have added it in the attached patch.

    I hope all this helps you, but don't hesitate to ask if you need more help.
     

    Attached Files:

  22. Filipinjo

    Filipinjo

    Joined:
    Jan 7, 2014
    Posts:
    22
    I have exactly the same problem... the Library deletion didn't help... my version of unity is 2017.3 and supertilemap is v1.4.7
     
  23. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Check this post, you should be able to fix it by following these instructions. Probably you have to remove the old file Tilemap.cs. If you update the tool, it adds or modify the files, but the updater doesn't remove any file.
    https://forum.unity.com/threads/released-super-tilemap-editor.387330/page-18#post-3241654
    Also, remember to exit unity before removing the Library folder, and open the project after removing it.
     
    Last edited: Feb 6, 2018
  24. digiwombat

    digiwombat

    Joined:
    Sep 26, 2013
    Posts:
    44
    Hey!

    A minor problem (and solution) in an otherwise great piece of work.

    Originally, I posted about an Out of Range exception when importing Tiled TMX maps, but I figured out the issue.

    If you try to import an Infinite Tiled TMX map, the importer does not account for the infinite map's use of a <chunk> element to hold 16x16 arrays of tiles.

    It decides there are 0 tiles since the XML structure is not what it's expecting.

    The easy fix is to just change your TMX (when importing) to be a non-infinite map. That's all.
     
    Last edited: Feb 10, 2018
    CreativeSpore likes this.
  25. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    Hello @CreativeSpore ,

    This may sound strange, but I'm working on using a tilemap to view a plain map and minimap of the game area (imagine like Super Metroid). My problem comes currently with trying to use the tilemap within Unity's UI canvas system. I'm able to parent the map to UI objects just fine, but I'm unable to use RectMask2D or Mask in order to prevent the map from being viewed beyond the boundaries of the container I'm trying to put it within.

    Is there any way to apply a mask to a tilemap, or am I just missing something obvious?
     
    Last edited: Feb 11, 2018
  26. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    The tilemaps are rendered using a MeshRenderer and maybe RectMas2D or Mask are not thought to be working with a MeshRenderer.
    But you can use this method:
    Texture2D mapPreview = TilemapUtils.CreateTilemapGroupPreviewTexture(STETilemap tilemap, TilemapGroup tilemapGroup = null);

    This will create a preview for a tilemap group, using the tilemap as reference for the pixels per units.
    It will include everything in the scene. But you can modify the code to render only some elements setting the camera cullingMask before call Render:
    previewCamera.cullingMask = 1 << layer1 || 1 << layer2 ...;
    previewCamera.Render();

    If you need more help let me know.
     
  27. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    Thanks! I'll try it out when I get home and let you know how it goes. :D
     
    CreativeSpore likes this.
  28. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    150
    Hmm, I updated to v1.4.7 (which required me to go through the Tilemap to STETilemap renaming steps). After testing the update out to make sure everything still worked, I tried to access TilemapUtils.CreateTilemapGroupPreviewTexture() but the method does not exist. Is this being included in a pending update? It's not in the static TilemapUtils class.

    EDIT: After some searching it appears to be in a TilemapUtilsEditor class.

    EDIT 2: First, I want to say that piping the result texture to a UI RawImage sitting on the UI Canvas does play nice with UI viewport masking. I've tried adapting the code and moving it over to TIlemapUtils, but I'm experiencing a few unrelated issues with attempting to render the tilemap to the target texture.
    1. If I try to call the method just after refreshing the target tilemap's data, I have to at the very least force waiting some fraction of a second before attempting to create the texture as updating the tilemap mesh seems to take longer than WaitUntilEndOfFrame() can allow.
    2. The resulting texture comes out smaller than intended even though the PixelToUnits value appears to be correct (my tilemap is set to 16 units). I'm guessing this has something to do with the calculated orthographic size not coming out quite right as the logic tries to leverage an existing camera to instantiate from.
    3. This method presents an interesting problem for me to sort out how to accurately center the map on a certain tile location (where the player currently is). I suppose the only way is to calculate and offset the UI object position that the texture gets sent to.
    EDIT 3: I was pretty much able to overcome my issues as such (solutions below mirror above issues I had):
    1. This wasn't a terribly problematic issue. I simply put the call to the method that generates the texture into a Coroutine and set my own sort of "isDirty" flag that would get changed once the process competed. This also kept me from attempting to move the map RawImage prematurely before the cell had been completely rendered.
    2. I scaled the resulting RawImage object up to 4.5 (though only arrived at 4.5 by eyeballing the result, so I'm sure there is a better way to get a more accurate result). I'd much rather sort out how to do manage it dynamically, as I assume I may run into an issue later as the map continues to grow in size.
    3. My goal was to ensure Tile(0,0) would be able to display in the center of the minimap so I had to create an X/Y offsets buffer. This was a bit more painful than I care to admit to solve because of the Left-to-Right and Bottom-to-Top nature of the Tilemap's grid system, but I ultimately worked out the X/Y offsets I needed based off the texture height and the increment values in order to move the map around in predetermined increments to keep them lined up along the checkered background image I had.
     
    Last edited: Feb 14, 2018
    CreativeSpore likes this.
  29. likwid

    likwid

    Joined:
    Apr 24, 2013
    Posts:
    16
    Hey there.

    Not sure if I'm doing something wrong here, but I'm using the Carpet Brush to draw the walls of my dungeon room. The walls have full colliders on them, but for some reason the room inside is being treated as a collider as well. As a result, any RigidBody2d object is getting pushed out of the room.

    I have tried replacing the Carpet Brush with a Road Brush, and the inside of the room works as intended, but this brush type is missing corner pieces needed for proper auto-tiling.

    This image shows the 2 rooms. The left room is the Carpet Brush and the right room is the Road Brush.
     

    Attached Files:

  30. SiliconAvatar

    SiliconAvatar

    Joined:
    Mar 23, 2014
    Posts:
    50
    I really enjoy this tool.

    Question:

    If I assign a prefab to the first frame of an anim brush, that prefab is placed wherever the anim brush is used, correct?

    Or am I supposed to assign a prefab to each frame of the anim brush?

    Thanks.
     
  31. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Good to know you found the answer to your questions.
    It's true that CreateTilemapGroupPreviewTexture wasn't moved to TilemapUtils in the current released version, I moved it in the next version that should be available during the next week.
    About scaling the tilemap, here are some tips in case you want to improve the resolution:
    previewCamera.orthographicSize = (previewCamera.pixelRect.height) / (2f * pixelToUnits);
    This line will make the camera size to adjust to the pixel size using the pixels per units value (in Unity it is called pixelToUnits in some cases so I left it with the same name).
    To calculate the player position in the output texture, you could try using previewCamera.WorldToScreenPoint to get the position for any element in the scene in texture coordinates and save that value.
    I am not sure why you had problems with the tilemap coordinate system Left-to-Right and Bottom-to-Top, because the texture has the same coordinate system.
     
  32. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    I have tried the same layout and it worked fine for me. Maybe it is related with the Unity version you are using. Could you tell me what version are you using and send me a test project to see what could be the problem?
     

    Attached Files:

  33. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Exactly, it will take the prefab attached to the first frame in the animation.
     
  34. likwid

    likwid

    Joined:
    Apr 24, 2013
    Posts:
    16
    I am using Unity 5.6.4. Also, I'm not sure that you set up your layout the same as me. The center tile in the carpet brush makes no difference in this case, because it's not used on the interior of the room. The interior is empty and has no tiles. The border of the room is created with the carpet brush and is 2 tiles wide all around. Please ensure you are doing this in your test. If this is the case and you are still not encountering this issue, I will set up a sample scene for you.
     
  35. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    I have tried again and it looks fine. Maybe it is related with polygon colliders. If you are using them it could cause some colliders lines to be outside the collider shape.
    upload_2018-2-18_11-55-37.png
    You can see the real collider lines if you enable Show Tile Chunks
    upload_2018-2-18_11-56-45.png
    But after trying different room rectangular shapes , it looks like it is working fine.
    upload_2018-2-18_11-58-24.png
    Send me a test project and I will check what is causing the issue.
     

    Attached Files:

  36. likwid

    likwid

    Joined:
    Apr 24, 2013
    Posts:
    16
    Email sent with a sample project.

    I'm guessing you didn't put a Collider2d and RigidBody2d on your character sprite. This is what is causing it to be pushed out of the room.
     
  37. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    I have checked the test and I know what is happening. Weird thing is, in your first screenshot it should work.
    It's related with how the colliders are generated.
    The tiles of a tilemap are created in children objects called tileChunks with a size of 60x60 tiles. The colliders are also created inside these children objects, so when the room is overlapping two chunks, the colliders are divided in two like in this case:
    NOTE: the red lines show the limit between chunks
    upload_2018-2-19_9-29-16.png
    I replied this case because it is what I saw in your first screenshot. In this case the inside and outside collider is connected by the point where the chunk ends
    But if the room is completely inside a chunk, the outside and inside colliders are created as two different colliders:
    upload_2018-2-19_9-31-30.png

    The colliders are convex what means, they create a collision area inside them.
    This is the reason why Polygon Colliders have a warning when they are selected in a tilemap, they can leave to this kind of behaviour.
    The best way to fix it is by using Edge Colliders:
    upload_2018-2-19_9-34-53.png
    It should work the same in most cases.
     

    Attached Files:

  38. likwid

    likwid

    Joined:
    Apr 24, 2013
    Posts:
    16
    Thanks for looking into this. However, switching the colliders to Edge rather than Polygon seems to cause issues with a* pathfinding detecting colliders properly. This was not an issue with Polygon Colliders.

    Are there any plans to make this asset work properly when using polygon colliders as a border for an area?
     
  39. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    If you change the pathfinding a little it could work with edge colliders.
    Lets ray you have in the code a place where it uses a raycast to check for a collision.
    You only need to check if at the raycast position there is a tile with colliders on it.
    Code (CSharp):
    1. public bool IsPassable(Ray ray)
    2. {
    3.     bool isBlocked = false;
    4.     for (int i = 0; !isBlocked && i < m_tilemapGroup.Tilemaps.Count; ++i)
    5.     {
    6.         STETilemap tilemap = m_tilemapGroup[i];
    7.         if (tilemap && tilemap.ColliderType != eColliderType.None && tilemap.IsGridPositionInsideTilemap(GridX, GridY))
    8.         {
    9.             Tile tile = tilemap.GetTile(ray.position);                  
    10.             isBlocked = tile != null && tile.collData.type != eTileCollider.None;                  
    11.         }
    12.     }
    13.     return !isBlocked;
    14. }
    15.  
    By the way, the tool includes a pathfinding system as well: MapPathFinding and PathfindingBehaviour.
    You can check an example in the Roguelike Demo scene.
    Finally, you can remove an optimization made for colliders to make them create a single collider for each tile, but it could be slow if you have big maps.
    upload_2018-2-20_10-27-45.png
     
  40. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Super Tilemap Editor v1.4.8 now available!

    Changelog v148:

    • ADDED Undo option in Paint tab to enable undo/redo while doing vertex paint on a tilemap
    • ADDED eBlengingMode.None that will just set the color, including the same alpha component
    • ADDED experimental option to set the SortOrder of tiles in the Rendereing options of a tilemap (Only BottomLeft and TopRight are available)
    • ADDED GetGridPosition to TilemapUtils. It works the same as GetGridX and GetGridY but returns a vector2 with both values.
    • ADDED GetOrCreateTileSprite to TilemapUtils to create an sprite from a tile of a tileset
    • ADDED STETilemap method GetTileObject to get the instance created when the tile prefab property is set.
    • ADDED SetParam(string, string) method in ParameterContainer
    • ADDED Default Tilemap Window in TilemapGroup to assign default tilemaps for each tile in the palette
    • CHANGED TilemapUtilsEditor.CreateTilemapGroupPreviewTexture has been moved to TilemapUtils to allow being used in game
    • CHANGED MapPathFinding.ClearNodeDictionary visibility from private to public
    • OPTIMIZED TilemapGroupEditor inspector view (with cache for tilemapSerialized and tilemapObjSerialized variables)
    • OPTIMIZED the tilemap DrawGizmos when drawing the colliders
    • FIXED Atlas Editor to keep the same tile order (usefull when adding extrusion to tilesets exported from Tiled tmx file or when using textures with multiple sprites)
    • FIXED EnumMaskField warning in Unity 2017
    • FIXED issue with Random Brush and Random Flags Enum
     
    Filipinjo likes this.
  41. Rabagast

    Rabagast

    Joined:
    Jan 30, 2013
    Posts:
    78
    Screen Shot 2018-03-03 at 17.48.56.png View attachment 268742 View attachment 268742 View attachment 268742 View attachment 268742 View attachment 268742 Hi!
    Just some questions:
    1. I try to create a new Atlas, but then I get this error.
    There is no tutorial on this in the document.

    NullReferenceException: Object reference not set to an instance of an object
    CreativeSpore.SuperTilemapEditor.AtlasCreatorEditorWindow.OnGUI () (at Assets/CreativeSpore/SuperTilemapEditor/Scripts/Tilemap/Editor/AtlasCreatorEditorWindow.cs:97)


    2. I want to make a kind of RoadBrush of these tiles in the screenshot. But in RoadBrush, itºs only one 3 slots where you place the vertical tiles, but I have one vertical left tile and one vertical right tile. Is it possible to create a brush so I can draw the level like in the screen without changing tiles?

    3. It's another Brush called Brush47. It's no tutorial on this. Can you explain me a bit what this is? I was just thinking I could use this for my tiles, but I can't get it to work.
    22
     
    Last edited: Mar 3, 2018
  42. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    HI there,

    The first error is because you didn't select a Tileset. But it shouldn't happen. It's a bug related with a small change that uses the tileset name to name the new atlas created. I have attached a fix for that in this post.
    You need to follow the steps in the help box appearing at the window bottom.
    upload_2018-3-5_10-8-25.png

    About the Road Brush, your case was to taken into account. But I think I could modify the road brush to take that into account. Could you send me your tiles to test it and be sure it's working?
    Road brush only takes into account the vertical and horizontal neighbors and for your case, you will need also take into account the 4 corner tiles when they have a diagonal neighbour. I think it could be made with 4 extra cases.

    And the Brush47 is a brush with all combinations possible to create terrain autotiling. You just need to follow the brush layout where the cyan area is the terrain and the grey area is empty. But I think I could fix it in the Road brush if you only need 4 extra cases.
    You can find more information here:
    https://gamedevelopment.tutsplus.co...ng-to-auto-tile-your-level-layouts--cms-25673
     

    Attached Files:

  43. Rabagast

    Rabagast

    Joined:
    Jan 30, 2013
    Posts:
    78
    Hi!

    Thank you for the answer. I sent you the tiles in an email.

    In the Atlas Creator, it says Tileset (Optional) So I don't need it. It's what I understand. Do I need to create the tileset in another program? Isn't the purpose with Atlas Creator that you can create a tileset from separate tiles I have?
    Under Atlas Settings. I can add textures there, but I will update the asset with the update you sent me. :)
     
  44. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    You can create a tileset from the Project Create menu:
    upload_2018-3-7_9-42-50.png

    But it shouldn't be needed to create an atlas. The exception was a bug created when I decided to use the tileset name for the atlas name, instead using "New Atlas". I forgot the case where the tileset could be null. It has been fixed in the package attached in the previous post.

    I have sent you a package with a demo and a prototype terrain brush using your tileset.
     
  45. Rabagast

    Rabagast

    Joined:
    Jan 30, 2013
    Posts:
    78
    Hi!
    Thank you so much. I replied our email. :)

    But to create the tileset from many tiles, can I do that with Super Tile Map Editor? Or do I need to do it in another program? For example I have 10 single tiles, and I want to add each of them to an existing tileset. Is that possible?
     
  46. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    Yes, you can do that. But take into account, you need to always add, and not remove previous tiles. And also in the same order. That is because there is an option to sort the tiles by name. You should name the tiles in order.
    The idea using the Atlas Creator is, you create an empty tileset (with no atlas or tiles assigned).
    Then you open the Atlas Creator Window:
    1. Select the new empty tileset or click Create Tileset
    2. Drag your tiles to the Tile Textures List (when you add new tiles you can just set the list to 0 items and drag all tiles at once to be sure you don't duplicate or miss anyone)
    3. Sort by name
    4. Create/update the atlas
    upload_2018-3-8_10-5-32.png
     
  47. Rabagast

    Rabagast

    Joined:
    Jan 30, 2013
    Posts:
    78
    I get this error message when I create atlas. I followed your 4-steps tutorial. And the tilesetAtlas was not in the project window.

    NullReferenceException
    CreativeSpore.SuperTilemapEditor.AtlasCreatorEditorWindow.OnGUI () (at Assets/CreativeSpore/SuperTilemapEditor/Scripts/Tilemap/Editor/AtlasCreatorEditorWindow.cs:104)
     
  48. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,186
    That is weird. I tried and it worked fine. It looks like the atlastexture is not being created for some reason.
    Could you send me a test project and tell me what version of Unity you are using?
     
  49. MartinMouritzen

    MartinMouritzen

    Joined:
    Jul 3, 2017
    Posts:
    9
    Hi CreativeSpore,

    Thanks for a great tool. I have somewhat of a newbie question, but I can't seem to figure it out (I watched all your YouTube videos to try and figure it out, so this is kind of a last chance :D )

    Basically as you can see in the screenshot, I have 3 types of terrain. I have them all in 47Brushes.

    I want to paint the darker brown onto the lighter brown, but then it starts tiling with the sand on the edges. I've tried using the brush groups, but I can't seem to get it right. Can you point me in the right direction?

    A side question would be... Is it possible to have a seperate brush, where the dark brown tiles to the sand, which is then automatically used when I paint the dark brown on the sand (as opposed to the light brown terrain) ?

    Thanks in advance! :)
     

    Attached Files:

  50. CreativeSpore

    CreativeSpore

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

    I'm afraid, the only way to do that is by using different tilemaps for each terrain.
    The brush47 can only be used for a terrain transition, but you can make the background to be transparent and use it as an overlay over other tilemap.