Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

SpriteTile, a fast dynamic tile system (RELEASED)

Discussion in 'Assets and Asset Store' started by Eric5h5, Dec 11, 2013.

  1. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Works here, but as I mentioned you can always use SetLayerPosition regardless of what the pivot points are.

    --Eric
     
  2. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    Perhaps this is another stupid question...but this is the issue im currently having. I have 4 layers: the main layer which is the ground (the one I want the player on), 2 layers behind that one for background type stuff, and 1 layer in front of it for overlay gfx.

    When I had just 3 layers (1 behind, 1 in front) everything was fine..however when I added the second background layer it gets drawn on top of the player and im not sure why.
    Layer 0 - Static Background that doesnt scroll
    Layer 1 - random tiles that I want to appear on the ground but BEHIND the player
    Layer 2 - Layer with my ground tiles
    Layer 3 - Overlay layer where tiles that I want to appear on the ground but be drawn ABOVE the player.

    I'm using an orthographic camera (therefore the Z index of the layers shouldnt matter?).

    Attached is a screenshot of what I mean. The grass tiles are properly getting drawn on the layer in front of the player, however the signs should be drawn behind the player. If I delete the background image layer it works as intended.
     

    Attached Files:

  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Did you rearrange the sorting orders in the "tags and layers" settings in Unity? SpriteTile uses them in numerical order, so they should look like this:

    layers1.png

    and not something like this:

    layers2.png

    You're correct that in orthographic camera mode, the z position doesn't matter.

    --Eric
     
  4. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    I had tried rearranging the sort orders in an attempt to figure out whats going on...however I returned them to the correct sequence. I have verified that the layer order in the SpriteTile editor matches the order of the sorting layers...however I still have the same problem as shown in the screenshot.

    Does the Z index of the camera matter? Perhaps the order of the layers are correct but I'm drawing the player sprite on the wrong layer? How do I "control" what layer the player is on?
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You would set the sorting layer on the player sprite renderer component. Also maybe the order in layer, for sorting within a given layer.

    --Eric
     
  6. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    Thanks for your help, I apologize for the noon questions!
     
  7. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    I am racking my brains with this one as it worked before but seems to elude me to figure out this time.

    No matter what I do it will not follow the pivot point of the tiles I have. I have them set up as sprites which are generated by from a sprite sheet. All have their pivots set to 'Bottom Left'. I have tried various ways but it still when drawing the tile I select the the editor plots it based off its center.

    Any ideas why it is doing this all of a sudden?
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Did you click "refresh" in SpriteTile?

    --Eric
     
  9. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    I've been playing around with the procedural demo and have been able to get that working in my own little test project. I'm looking to create an "Infinite scrolling" procedural level. I'm trying to figure out the best way to do this..

    Since I have to set a mapsize, My thoughts on how to achieve this would be to create a level say 100x20. Set up a row of triggers at say x = 80 that will create another level and position it so that it seemlessly transitions into the next. Would this type of approach work or could you point me in the direction I need to be going?
     
  10. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Like most things, there are many different ways to achieve your infinite scrolling level.

    The first, and quite common, method is to simply create one very long level in the map editor.
    At the end of the level make it so that last "screen" ties back in to seamlessly connect with the very first "screen" of the level. Now, you can simply scroll until you reach the last screen of the level is displayed and at that point simply reset the position so the start of the map is displayed again.

    A second, and very simple procedural way, of building your infinite scrolling level is to build your levels in "chunks".
    For this, you just choose the size of each section. Say each chunk is the size of 3 screens meaning each chunk provides enough of a level for 2 full screens of scrolling. Now you just make it so the last part of each section can align with the first part of the other sections. Or at least some of the sections. Once you have scrolled each chunk as far as possible you then randomly choose another chunk and position the view so the beginning of the new chunk is now displayed on the screen. Not every chunk needs to connect with every other. For example, maybe chunk 1 can connect only to chunk 2. Then maybe chunk 2 can connect to chunk 1 and chunk 3. Chunk 3 can connect to chunks 2, 4 and 6. And so forth.

    A third way is as you scroll each tile row or column off the visible display you dynamically rebuild the map.
    This method would work similar to the first only you just need to define about two screens worth of map. You rebuild it on the fly as it scrolls so that when the first screen worth of map scrolls off you rebuild the beginning of the map. This is definitely more complicated but still achievable.

    Basically, you can make this stuff as easy or hard on yourself as you want to.
     
  11. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    Thanks for the reply Just a couple of questions based on each option.

    Option 1 - The only thing I'm not entirely sure on how to do is once reaching the end of the level, how do I seamlessly transition back to the beginning again?
    So theoretically I could Create an extremely long level, have a defined start and end point, and proceduraly generate the in between. Once I reach the end I go back to the beginning, and can randomly generate the body of the level again?
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd recommend using GetMapBlock and SetMapBlock, where you copy a block from the end of the level when the player gets near the end, then paste it into the beginning, then reset the player position back to the beginning. Then you can continue scrolling until nearing the end again, etc.

    --Eric
     
  13. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    Yep that makes sense. My only thought/concern would be wouldnt changing the players position create a not smooth transition?
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The transition would be unnoticeable; the idea is that you copy the area the player is in, so when you move the player, it looks exactly the same. Say the level is 100 units long, the player is at position 90, so you copy the tiles from 80-100 and paste them in to position 0, and move the player back 80 units. (Actual numbers would be different of course depending on tile size etc.)

    --Eric
     
    GarBenjamin likes this.
  15. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    You reposition the player and all other objects by the same offset as the map.
     
  16. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Exactly as Eric just stated.
     
  17. jimdubbs

    jimdubbs

    Joined:
    Dec 3, 2012
    Posts:
    12
    Ah gotcha ok thanks!

    Something else I'm running into..can you not call LoadGroups without LoadLevel? I created a group that has a couple of level "chunks". I then create a level programatically and want to use CopyGroupToPosition to essentially paste the chunks in to dynamically create my level. However when I get this:

    NullReferenceException: Object reference not set to an instance of an object
    SpriteTile.Tile.ForceCameraUpdate ()
    SpriteTile.Tile.LoadLevel (System.Byte[] bytes, Boolean loadGroup, Boolean loadBlock)
    SpriteTile.Tile.LoadGroups (UnityEngine.TextAsset groupFile)
    LevelManager.Start () (at Assets/LevelManager.cs:13)

    Heres my code:
    Code (CSharp):
    1. public TextAsset myLevel;
    2.     public TextAsset mainGroup;
    3.     // Use this for initialization
    4.     void Start () {
    5.  
    6.         Tile.SetCamera();
    7.         Tile.LoadGroups(mainGroup);
    8.  
    9.         buildLevel();
    10.         //Tile.LoadLevel(myLevel);
    11.     }
    12.     void buildLevel() {
    13.         Tile.NewLevel (new Int2(40, 15), 0, 2.56f, 0.0f, LayerLock.XandY);
    14.         Tile.AddLayer(new Int2(40, 15),0,2.56f,0.0f,LayerLock.None);
    15.         Tile.SetTile(new Int2(12, 7),0, new TileInfo(2,0),true);
    16.         //Tile.SetTileBlock (new Int2(0, 3), new Int2(40, 3),1, new TileInfo(1,60),true);
    17.         Tile.CopyGroupToPosition (new Int2(0, 5),new Int2(0,0),1, 0, 0);
    18.     }

    Its failing on the LoadGroups Method. Should I create an empty Level and just fill it in at runtime as opposed to creating the level at runtime?
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Good catch; I'll fix that. In the meantime, it will work if you call NewLevel before calling LoadGroups; the rest (AddLayer etc.) can be called afterward.

    --Eric
     
  19. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    @Eric5h5

    I am clicking refresh afterwards.

    Going to do some more tests just to make sure it has nothing to do with a debilitating yet powerful overwhelmingly vicious though disorder know as a 'Brain Fart'..... :)
     
  20. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Okay, well scratch my previous post.

    At this point I have no idea how to solve the issue with gaps appearing between the tiles.

    I have tried going into the Sprite Tile Resources folder and setting Pixel Snap on the materials but they already had it on.
    I also created my own material and clicked on Pixel Snap. But I see no way to actually use that for SpriteTile. But like I said, it looks like SpriteTile is already using the Pixel Snap anyway. I did use it for my character sprites though. I have the Non-Transparent box checked for my tiles in the editor so, based on the documentation, it sounded like using the SetTileMaterial wouldn't help anyway because it should be using one of the materials that already has Pixel Snap on.
    At any rate, this did not fix the issue.

    I have tried resizing my map tile dimensions. Instead of 0.32 I set the size to 0.31999, then to 0.3199 then 0.319.
    This had no noticeable effect.

    I then tried using the SetTileScale function right after loading the map. I tried 1.001f and even 1.01f and 1.02f. This had no noticeable effect.

    I am really at a loss. And the thing that is frustrating me battling this is it seems to be completely random with no rhyme or reason as to why it happens.

    Sometimes, I open the project in Unity and run it and there are no gaps at all. It all looks sharp! Then after I work on the code, say I update the script for my Player Game Object. Run a test again and there the gaps are.

    Is there any solution to this?
     
  21. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The four default materials are in the SpriteTile/Resources folder; you can enable pixel snap for those (it's off by default). If you want to use your own material then you need to use SetTileMaterial.

    As for SetTileScale, there's a bug which was introduced with multi-camera support since I failed to update the loops properly. It's fixed in the next version, but if you want to fix it yourself now, then you'll see this in the SetTileLayerScale function:

    Code (csharp):
    1.             for (int y = 0; y < tileSprites[layer].Count; y++) {
    2.                 for (int x = 0; x < tileSprites[layer][y].Count; x++) {
    3.  
    It should read:

    Code (csharp):
    1.             for (int y = 0; y < tileSprites[i][layer].Count; y++) {
    2.                 for (int x = 0; x < tileSprites[i][layer][y].Count; x++) {
    3.  
    --Eric
     
  22. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Sorry Eric5h5,

    I'm still getting the issue with tiles being drawn centered on the grid. Anything else I should look for?
     
  23. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    I already checked the materials in the Sprite Tile Resources folder. The Pixel Snap checkbox was already checked for all of them. I probably did it as soon as I purchases it because I read all of the posts on the forum here and learned about the pixel snap.

    It is a very strange thing. It seems to be based on the images / colors used for the tiles themselves.
    Because I just tried replacing some tiles with different images (changing the color) and it caused a lot more of the artifacts to appear.

    I like SpriteTile a lot as far as being able to knock out maps quickly and such. But I need a way to get rid of these glitches.

    Also, I remember reading a post in this forum where someone said ALL tile add-ons for Unity have this issue. It makes me wonder if it should be approached from a different angle. If trying to build a world out of hundreds of individual primitives (planes or whatever is being used) causes this issue then it might be better to create one large texture, say 1024 x 1024, render all of the visible map directly to that texture and then display it on screen?

    I'll see if the next update gets rid of the issue.
     
  24. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    I have researched this gap issue issue thoroughly. I found numerous posts on both Unity3D.com and other websites talking about this issue in Unity3D. It seems to be something inherit in Unity3D itself.

    I now have a few things to try as soon as I am off work:

    1. Changing the pixels to units ratio from 100 to 1. This should help to alleviate any issues caused by fractional positoning values since I will basically be dealing with integers instead of floats.

    2. Make my orthographic camera size an integer instead of a decimal value. The issue actually occurs regardless of using Ortho or Perspective but everything I read recommends Ortho to get a better pixel perfect display.

    3. Change my tile images. This one I am not too keen on but the idea is instead of having 32x32 pixel tile images make 34x34 pixel tile images. Adding a border around the tiles basically copy the top of tile and paste it down one pixel higher. Duplicate the other edges the same way. I am willing to do it if it resolves the issue.

    The crazy thing is we are battling something in Unity itself. When you research the issue you find different solutions worked for different people and while solution A may have worked for some people it did not work for other people. Pixel snap. Integer camera size. Int camera positioning. Many different things worked for some but not for others. However, other things did work for most of them.

    I hope Unity addresses the root cause.
     
  25. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You can use SetTileScale effectively. See above for the bugfix. Using a large texture for a tilemap would be very inefficient for several reasons (speed, memory usage being the main ones).

    @Amon: sorry, no idea. I've never seen any case where changing the pivot and clicking "refresh" in the TileEditor doesn't work.

    --Eric
     
  26. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    It's strange to me that doing something like drawing all of the textures (tiles) onto large texture then displaying that on a quad would be ineffient. This kind of thing was common back in the 2D gfx cards days even. I guess in some ways the 3D cards are less capable than 2D! Lol

    I didn't see any source files but will look again when I get a chance. Maybe on lunch break.
     
  27. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Uploading large textures is very slow, so that method would rule out tile animation, not to mention moving the camera. The source files are always included in all my assets, in a package labeled "Source". Maybe I should choose a more obvious word. ;)

    --Eric
     
    GarBenjamin likes this.
  28. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Lol. Yeah I found it. The whole unity package thing threw me off. I was looking for a folder with the source or a zip file etc. I am still not used to Unity3D's way of doing things. I may try to set up a new VS solution and class library project tonight, pull the files in and see if I can get it building.

    I will probably try the other things first that I found from researching online this morning.
     
  29. goranobradovic

    goranobradovic

    Joined:
    Mar 11, 2014
    Posts:
    16
    I am not sure am I missing something, but is there a simple way to flip a tile in tile editor? Like horizontal or vertical flip.
     
  30. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Not currently. Flipping sprites by inverting the X or Y scale breaks batching, so it's probably best just to have flipped versions of the sprites themselves.

    --Eric
     
  31. noanoa

    noanoa

    Joined:
    Apr 17, 2014
    Posts:
    225
    Hello, will you answer a few questions?

    Can the editor be used for terraria type of map? Like 5000x5000 tiles per map? Also can it update the small portion of map without updating the entire map?(so it won't lag when you change tiles at runtime).

    Also, can you use prefab(which contains 3d gameobject) as a tile and control drawing order like other 2d tiles?(no need for caching, combining meshes etc)
     
  32. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, not a problem.

    Yes, changing a tile only requires changing a single sprite so it's about the fastest you can get.

    No, it's 2D sprites only. You can mix it with 3D objects and control the drawing order as you like, but they would be separate and not part of the tile system.

    --Eric
     
    noanoa likes this.
  33. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Moving a tile via code:

    Is it possible for an example UnityScript that shows how to move, within the game at runtime, a tile or several tiles using GetTile( transform.position )? Basically when my character bumps a tile I want to access its transform and then move it where I want. An example of moving multiple tiles would be greatly appreciated.
     
  34. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd say the best thing would be to use GrabSprite to convert a tile to a sprite, which you can move as a normal GameObject (or multiple GameObjects if you use GrabSprite on more than one tile), and then use PutSprite to convert it back into a tile if needed. The code example in the docs for PutSprite is similar to what you're asking.

    --Eric
     
  35. Fohristiwhirl

    Fohristiwhirl

    Joined:
    Sep 1, 2014
    Posts:
    5
    Are these lines due to sprite tearing or another problem? I have tried most of the fixes you have suggested for sprite tearing. I set my camera background colour to a bright orange. If it was tearing wouldn't it be the orange colour visible in the lines as there is nothing else being rendered behind the tiles?
     

    Attached Files:

  36. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I think that's a problem with the tile textures themselves. How are you making them? You're correct that if it was tearing you'd see the camera background color.

    --Eric
     
  37. Fohristiwhirl

    Fohristiwhirl

    Joined:
    Sep 1, 2014
    Posts:
    5
    Thanks for the clarification. By the way I would like to add that this is a fantastic tool for a great price. In my opinion one of the best things (that sets it apart) is its concise easy to understand documentation.
     
  38. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Thank you! But we didn't resolve the issue. ;) How are you making the textures? If you're making them as an atlas, with all the tiles right next to each other, then that can result in artifacts around the tile edges. You can use 1 pixel of padding around the tiles, using transparent pixels for the padding. Then you can use "Automatic" in the sprite editor to slice them, instead of using a grid; or you can still use grid, but set the offset and padding values appropriately.

    Also, the filter mode for the texture should be point rather than bilinear. It's a little trickier if you want to use bilinear, since the padding should extend the colors of the tile rather than being transparent (you can use Photoshop filters such as Solidify for this), otherwise you still get artifacts.

    If you have Unity Pro, you can use single images instead of an atlas, since in this case you can use the auto-atlas functionality, which fixes these issues automatically.

    In my experience, using an atlas with padding, where the padding extends the colors of the tile, results in 100% perfect results in all cases, without having to use SetTileScale to fix the "occasional tile gap" issue.

    --Eric
     
    Fohristiwhirl likes this.
  39. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Hi Eric5h5,

    After grabbing the tiles I want and finishing level setup I'd like to completely remove the Level created by SpriteTile. I have tried a few things and one works but leaves behind, no matter what I do, a pink filled in square where the tile used to be.

    How would I go about completely removing the level but still being able to load the next level when the current one is finished?

    Ta!
     
  40. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Tile.EraseLevel().

    --Eric
     
  41. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Tried that already m8. When using that after grabbing the tile it leaves behind a pink square where the tile used to be.
     
  42. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I don't see any pink squares when using code like this:

    Code (csharp):
    1. Tile.LoadLevel (level);
    2. var sprite = Tile.GrabSprite (Int2.zero);
    3. Tile.EraseLevel();
    --Eric
     
  43. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    After loading the SpriteTile Level and doing what I need to set it up i.e. including Grabbing Sprites, I call Tile.EraseLevel() at the end of it.

    This is what happens after I call Tile.EraseLevel().



    Code (JavaScript):
    1.     curNumberOfTiles = totalTiles + 1;
    2.     Tile.EraseLevel();
    3.  
    4.    
    5. }
    6.  
    7.  
    8. function Start () {
    9.     mapSX = 12;
    10.     mapSY = 11;
    11.     Debug.Log(curNumberOfTiles);
    12.     //Debug.Log(numPurpleTiles);
    13.  
    14.     direction = -1;
    15.     canMove = 1;
    16.     currentCubesStopped = curNumberOfTiles;
    17.     curentCubesMoving = 0;
    18.    
    19. }
     
  44. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd need some more info; as I mentioned, the coded I posted works without any pink squares.

    --Eric
     
  45. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Hmm! Could the 2DToolkit tk2dCamera I use to manage aspect ratios and resolution changes be playing up a bit with SpriteTile?
     
  46. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I have no idea...what does it do?

    --Eric
     
  47. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    I think I found the issue. When Grabbing a tile ( Tile.GrabSprite ) it seems not to grab the default material. Thus far I've been able to reproduce this consistently when using the tk2dCamera.

    After grabbing the sprite you have to access its SpriteRenderer and assign the default sprite material to it. When that's done everything works like a charm.
     
  48. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The grabbed sprite automatically uses whatever material is used by that tile, actually.

    --Eric
     
  49. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Not when using the tk2dCamera for some reason which was the issue I was having. I can reproduce this every time when using the the tk2dCamera. When using the default unity camera it works perfectly.

    The issue is not with SpriteTile it is with tk2dCamera and whatever funky stuff it is doing that causes the incompatibility.
     
  50. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's really weird...I have no idea how a camera could affect the sprite material.

    --Eric