Search Unity

SpriteTile, a fast dynamic tile system (RELEASED)

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

  1. JayJennings

    JayJennings

    Joined:
    Jun 24, 2013
    Posts:
    184
    And, as long as I'm here... v2.12 won't allow me to save a level by hitting the Save As button. I can save by using the Alt-S key or by closing the window and telling it to save at the dialog that pops up, but the regular button isn't working for me. (I'm using latest public release of Unity on a MBP.)

    Jay
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I can't see any problems with that working here, sorry. The button and the keyboard command both use the exact same code, so unfortunately I have no ideas, other than try making a new project and see if that helps.

    --Eric
     
  3. JayJennings

    JayJennings

    Joined:
    Jun 24, 2013
    Posts:
    184
    I figured it might be a "Jay only" problem since I didn't see anyone else mention it. But just in case it's something on your side, here's the error that shows in the console when I try to save with the button:

    DirectoryNotFoundException: Could not find a part of the path "/Users/jay/Documents/Unity5 Projects/Word Dungeons/Assets/Maps/Level02.bytes/Level02.bytes".
    System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/FileStream.cs:292)
    System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
    (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int)
    System.IO.File.Create (System.String path, Int32 bufferSize) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/File.cs:135)
    System.IO.File.Create (System.String path) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/File.cs:130)
    System.IO.File.WriteAllBytes (System.String path, System.Byte[] bytes) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/File.cs:594)
    FileIO.Save (Boolean saveGroups, Boolean saveAs)
    TileEditor.LevelControls ()
    TileEditor.OnGUI ()
    System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)

    Jay
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    "Maps/Level02.bytes/Level02.bytes" can't be a valid path for obvious reasons, though I don't know how that path could be attempted in the first place. Especially since the keyboard and button run the same code, as I mentioned.

    --Eric
     
  5. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    Free A* Pathfinding Project. I'm using it with SpriteTile.
     
    JayJennings likes this.
  6. AndyGFX

    AndyGFX

    Joined:
    Jan 13, 2012
    Posts:
    98
    Hi,

    a few day I working with SpriteTile and I have an idea for making user defined groups more universaly.
    Now is TerrainGroup created as list of free and blocked position lookup table but is locked for one type. My idea is described in pptx file here:

    https://www.dropbox.com/s/9oms7zn67gjjnft/UniMarchingSquares.pptx?dl=0

    for test decoding is used this small image where is described existing Terrain group.

    Code for convert image to marching square rules for SpriteTile is below.
    After Build is created dirToFreeCheck and dirToBlockedCheck and indices list for tileID, -1 = unused cell for drag&drop.
    Again, just idea, and maybe doesn't work and never will be. ;)

    Code (CSharp):
    1. using SpriteTile;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. [System.Serializable]
    7. public class ST_MarchingSquaresParser
    8. {
    9.     // indices count
    10.     public int count = 0;
    11.  
    12.     // cells count in x direction
    13.     public int width = 0;
    14.  
    15.     // cells count in y direction
    16.     public int height = 0;
    17.  
    18.     // list of used indices
    19.     public List<int> indices;
    20.  
    21.     // list of all 'must be' free cells for merching square investigation
    22.     public List<Int2[]> dirToFreeCheck;
    23.  
    24.     // list of all 'must be' blocked cells for merching square investigation
    25.     public List<Int2[]> dirToBlockedCheck;
    26.  
    27.     // marching squares template
    28.     private Texture2D imageMatrix;
    29.  
    30.     // lookup table for inverted y texture coordinate
    31.     private int[] iY;
    32.  
    33.     private List<Int2> tmpBlocked;
    34.     private List<Int2> tmpFree;
    35.  
    36.     /// <summary>
    37.     /// Constructor
    38.     /// </summary>
    39.     public ST_MarchingSquaresParser()
    40.     {
    41.         this.dirToBlockedCheck = new List<Int2[]>();
    42.         this.dirToFreeCheck = new List<Int2[]>();
    43.         this.indices = new List<int>();
    44.         this.tmpBlocked = new List<Int2>();
    45.         this.tmpFree = new List<Int2>();
    46.         this.count = 0;
    47.         this.width = 0;
    48.         this.height = 0;
    49.     }
    50.  
    51.     public void Build(Texture2D matrix)
    52.     {
    53.         this.imageMatrix = matrix;
    54.         this.iY = new int[matrix.height];
    55.         this.CreateInvertedY();
    56.  
    57.         // clear list of direction to check
    58.         this.dirToBlockedCheck.Clear();
    59.         this.dirToFreeCheck.Clear();
    60.         this.indices.Clear();
    61.         this.count = 0;
    62.  
    63.         // get cells count in marching template
    64.         this.width = matrix.width / 3;
    65.         this.height = matrix.height / 3;
    66.  
    67.         // parse texture by cells
    68.         for (int x = 0; x < this.width; x++)
    69.         {
    70.             for (int y = 0; y < this.height; y++)
    71.             {
    72.                 this.GenerateMarchingSquare(x, y, this.count++);
    73.             }
    74.         }
    75.         Debug.Log("Done");
    76.     }
    77.  
    78.     /// <summary>
    79.     /// Generate SpriteTile rules for TerrainLookUp table, where is stored list of blocked and free directions
    80.     /// </summary>
    81.     /// <param name="x"></param>
    82.     /// <param name="y"></param>
    83.     /// <param name="idx"></param>
    84.     public void GenerateMarchingSquare(int x, int y, int idx)
    85.     {
    86.         // calc center of current 3x3 marching square
    87.         Int2 center = new Int2(x * 3, y * 3) + Int2.one;
    88.  
    89.         // Check if cell is used for Marching squares
    90.         // Color = Color.Clear = RGBA[0,0,0,0] => NOT
    91.         Color cell = this.imageMatrix.GetPixel(center.x, center.y);
    92.         if (cell.a == 0f)
    93.         {
    94.             this.dirToFreeCheck.Add(new Int2[0]);
    95.             this.dirToBlockedCheck.Add(new Int2[0]);
    96.             this.indices.Add(-1);
    97.             return;
    98.         }
    99.  
    100.         // reset direction lists for current marching square
    101.         tmpBlocked = new List<Int2>();
    102.         tmpFree = new List<Int2>();
    103.  
    104.         // check all pixels around center
    105.         this.CheckPixelInSquare(center, Int2.up);
    106.         this.CheckPixelInSquare(center, Int2.upRight);
    107.         this.CheckPixelInSquare(center, Int2.right);
    108.         this.CheckPixelInSquare(center, Int2.downRight);
    109.         this.CheckPixelInSquare(center, Int2.down);
    110.         this.CheckPixelInSquare(center, Int2.downLeft);
    111.         this.CheckPixelInSquare(center, Int2.left);
    112.         this.CheckPixelInSquare(center, Int2.upLeft);
    113.  
    114.         // store generated directions
    115.         this.dirToFreeCheck.Add(this.tmpFree.ToArray());
    116.         this.dirToBlockedCheck.Add(this.tmpBlocked.ToArray());
    117.         this.indices.Add(idx);
    118.     }
    119.  
    120.     /// <summary>
    121.     /// Check pixel color and add direction to list
    122.     /// </summary>
    123.     /// <param name="pos">center of marching square</param>
    124.     /// <param name="chkDir">direction to checked pixel</param>
    125.     private void CheckPixelInSquare(Int2 pos, Int2 chkDir)
    126.     {
    127.         Int2 chkPos = FixedSum(pos, chkDir);
    128.         Color cell = this.imageMatrix.GetPixel(chkPos.x, chkPos.y);
    129.         if (cell == Color.red) this.tmpBlocked.Add(chkDir);
    130.         if (cell == Color.green) this.tmpFree.Add(chkDir);
    131.     }
    132.  
    133.     /// <summary>
    134.     /// Create lookup table for invereted texture y coordinate
    135.     /// </summary>
    136.     private void CreateInvertedY()
    137.     {
    138.         for (int i = 0; i < this.imageMatrix.height; i++)
    139.         {
    140.             this.iY[i] = this.imageMatrix.height - i - 1;
    141.         }
    142.     }
    143.  
    144.     /// <summary>
    145.     /// Sum center of cell and direction for read correct position from texture
    146.     /// </summary>
    147.     /// <param name="pos"></param>
    148.     /// <param name="offset"></param>
    149.     /// <returns></returns>
    150.     private Int2 FixedSum(Int2 pos, Int2 offset)
    151.     {
    152.         Int2 res = Int2.zero;
    153.         pos.y = this.iY[pos.y];
    154.         res = pos + offset;
    155.         return res;
    156.     }
    157. }
     
    Last edited: Oct 18, 2015
  7. nadhimali

    nadhimali

    Joined:
    Apr 4, 2015
    Posts:
    17
    OK This asset is perfect however I have a problem, in a horizontal scrolling level with multi-layers, How to change each layer scrolling speed .example background sky is slower than the actual game ground
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Use a perspective camera instead of orthographic, then just set the Z distance of the layers to achieve the desired effect.

    --Eric
     
  9. nadhimali

    nadhimali

    Joined:
    Apr 4, 2015
    Posts:
    17
    I did't get it , do you mean i need to use multi cameras one for background (perspective) and the other for from ground (oath) ?
     
  10. nadhimali

    nadhimali

    Joined:
    Apr 4, 2015
    Posts:
    17
    I did it and it works, however it is creating issues where background came in front of player when using two cameras, one is perspective only dedicated for parallel scrolling . i think i'm missing something
     
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Just use one camera.

    --Eric
     
  12. AndyGFX

    AndyGFX

    Joined:
    Jan 13, 2012
    Posts:
    98
    Hi,

    I have used 5 layers in map 128x128. Layers 0-2 are filled with tiles (landscape), layer 3 is empty now, and in last layer I have used trees (~50), When player is in move, in any diagonal direction, layer wisth triees shaking, not big but is it visible :(. All trees are with order id from up up to down (like is desc. in doc), I have in code now any parts with performance issiu.

    I can't find where is problem.

    Andy.
     
  13. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'm not able to duplicate anything like this; I'd need more info (code etc.).

    --Eric
     
  14. AndyGFX

    AndyGFX

    Joined:
    Jan 13, 2012
    Posts:
    98
    Hi,

    uff - long night, I finaly found what was problem.
    Looks like Unity doesn't like custom sprite pivot in values like this [0.45789,0.212312]. fixed to [0.5,0.2] was solution.

    For future and for other users one hint:
    custom pivot format: 0.0
    (max one decimal place)

    Andy.
     
  15. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Hi everyone,

    I'm new to a lot of this so apologies for the very simplistic nature of my question. Basically I'm using the GetMapBlock/SetMapBlock approach to infinitely scroll the map across, but when I 'shift' the map to the beginning SetMapBlock is complaining that the size exceeds the map e.g. :

    Now, I'm not quite sure why this is complaining. I've grabbed a map block of 27 x 200 tiles from the end of the map, and attempting to insert them to the start of the map, at 0 x 199. The x looks ok at 0, given that the block is only 27 wide, and the y position at 199 should accommodate the 200 tiles height - so I'm not really sure why it's complaining.

    Any ideas? Sure it's probably an oversight on my part, but I just can't see it!

    Thanks in advance!
    Tony
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Using a position of (0, 199) with a map size of (215, 200) can't work, since 199 + 200 = 399.

    --Eric
     
  17. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Thanks Eric. So have I got the wrong end of the stick with the pasting? I thought 0,199 would be the top left corner of a map this size, so if it's zero based would accommodate the height of 200?

    Sorry for being a bit dim!
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    0, 199 is indeed top-left. As noted in the docs, the position you use with SetMapBlock is bottom-left. So, as mentioned above, 199 (where you start) + 200 (the amount you're pasting into the level) = 399. That won't work since the map size is 200; you're limited to 0-199 for the coords.

    --Eric
     
  19. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Ah missed the bottom left bit in the docs. Thanks Eric, consider me suitably chastised!
     
  20. Dayhawk123

    Dayhawk123

    Joined:
    Sep 27, 2013
    Posts:
    4
    For some reason this is not working. Having read the thread a previous person was having a similar issue of mine where their level is not appearing. As you can see it is running and it does appear that it loads some of the SpriteTile objects.

    upload_2015-10-24_1-36-51.png

    But no matter what I do, I can't get it to show my level.

    upload_2015-10-24_1-38-15.png

    This is just a test level.

    upload_2015-10-24_1-40-23.png

    I have adjusted the camera and so far it has had no effect.
     
  21. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Not sure if this will help but I had a similar issue recently using orthographic. The camera was set to Z =0, but it needed to be 1. As soon as I did that my level popped in. Might be worth a shot.

     
  22. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, the camera needs to be positioned where it can see the tiles. Use the preview function in the TileEditor and use that to position the camera. The tile objects are always created regardless, even if the camera can't see any tiles, in which case they are all empty.

    --Eric
     
  23. AndyGFX

    AndyGFX

    Joined:
    Jan 13, 2012
    Posts:
    98
    Hi Eric5h5,

    I found method GrabSprite for get gameObject from tile. Do you have any other solution for return gameObject but without instantiate new one in scene?. I think that missing any command for return gameObject from scene or method, which helps manage tile/sprite gameObject by user from script, for example to attach component when user don't use SpriteTile editor and map is created proceduraly. I can't find any method for this situation.

    Andy.
     
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's not possible; tiles aren't GameObjects and can't have components attached to them.

    --Eric
     
  25. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Well, I'm struggling to get my head around this - so I really need some help pushing in the right direction which I'd really appreciate.

    I'm using the GetMapBlock/SetMapBlock approach to keep the level scrolling by wrapping around. I get the concept - but what I'm struggling with is handling the coordinates system, and how to actually get it to perform smoothly.

    I've got the level loading, and it initialises so that it starts in the bottom left of the level :

    Code (CSharp):
    1. // Start in the bottom left of the map
    2.         offsetValueWidth = (Camera.main.orthographicSize * Camera.main.aspect);
    3.         offsetValueHeight = Camera.main.orthographicSize;
    4.  
    5.         cam.Translate (new Vector3(offsetValueWidth,offsetValueHeight,0f));
    That works fine - so all good so far. All of this is just test code, btw, so apologies for the crudeness. I then move the camera during Update to just keep on scrolling :

    Code (CSharp):
    1.     void Update(){
    2.  
    3.         var wantedPos = cam.position;
    4.         wantedPos.x = Mathf.Clamp (wantedPos.x + direction, 0.0f, maxCamPosX);
    5.         cam.position = Vector3.Lerp (transform.position, wantedPos, followSpring * Time.deltaTime);
    6.  
    That's also working fine. I then work out which tile I've 'reached', and if it's towards the end of the map I then perform the copying logic. I work out the tiled I've reached using :

    Code (CSharp):
    1.         Int2 mapPos;
    2.         Tile.ScreenToMapPosition (cam.position, out mapPos);
    Now, I know that the tile.x value will be the tile in the middle of the screen. So, at the moment I copy the map data for the whole height of the map, from the current tile - half the screen up to the end of the map, and also the map data from before that, and effectively 'swap' them around, then shift the camera back to the original start. Apologies for the lack of code, but it's that bad, plus it just doesn't work.

    The problems I have range from experimentation, causing things like :

    - It seems to roughly work, but noticeably 'jumps' - which varies depending on how fast I go across the map. The biggest problem is making it look as if the camera never switched coordinates - I just can't seem to place it correctly.
    - When it's about 99% there, it's still jumping, by a good 2 or 3 tiles.

    I tried adjusting the tile pivots which helped line up the bottom left, but that just seems to have made things worse.

    I guess what I need is a very simple explanation of how to do this - the biggest problem I have is understanding the units and how setting the speed of the level is effecting the copying process. For example, should I copy based on my pixel position or by the tile position as I currently am - and if so, how much do I adjust the camera position by to account for the fact that it won't be necessarily lined up with tile boundaries - which I suspect is what is causing by jumps.

    I also can't get my head around the fact the camera is, at 0,0, in the middle of the screen - and thus the map also starts there - so I have to offset it to fill from the bottom left up.

    The more I think about it, the more my head hurts - I need a shot of sanity please if anyone can spare the time!

    Thanks in advance,
    Tony
     
  26. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    If you know the camera position on the left side of the map, and the camera position on the right side, then you just have to subtract the difference to swap back from right to left.

    --Eric
     
  27. dsims

    dsims

    Joined:
    Oct 26, 2015
    Posts:
    1
    I want to load tile sprites dynamically (created by players). I know it's not currently supported by you, Eric, but would it theoretically be possible with custom code to add or modify sprites/textures to the tileset at runtime?

    (Sorry I'm new to Unity and don't quite understand the asset limitations, coming from HTML5 land)
     
  28. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    SpriteTile depends on assets in the project, which as far as I know can't be modified at runtime (in a build, I mean, rather than in the editor).

    --Eric
     
  29. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Morning Eric,

    Thanks for replying. I think I get the camera repositioning - the bit I'm really struggling with is knowing from which tile I need to copy from, given that the camera is in the middle of the screen.

    For example (I'll stick with just X here, as I copy the whole of Y anyway), if the map is 100 tiles wide, and the screen is 20, let's say - when I reach tile 70, I know that there'll be 10 tiles to my left, and 30 to my right - so at the moment I try and copy from position 60 - 100 into 0,0 - then swap position 0-60 into 40,0. That's ok if I'm bang on the tile boundary, but if I'm moving at pace sometimes the camera will be a few pixels into the tile - and that seems to cause my juddering when I nearly nail it. I can work out which tiles I need but I'm not 100% sure if my method in doing so is correct using ScreenToMapPosition and the position of the camera, which is central to the map.

    This probably doesn't make sense - and I'm confusing myself. I just can't seem to find any concrete coding examples - then I think I'd get it - even if it's just pseudo-code.

    EDIT: I did a bit more testing at lunch. Rather than using Lerp I set the position exactly, so that it'd move exactly one tile at a time to the right. So, when I check the map position using ScreenToMapPosition, it correctly reports 0,0 as my location. As I step through, each click of the progress button moves exactly one tile, and it increments by one, so 1,0 - 2,0 - 3,0 and so on - which I'd expect.

    I then wait until I hit tile 163,0 so that I can perform the reset - or at least, I think I am. But something weird is going on. When I first start, position 0,0 is showing on my screen in the bottom left. So I'd expect, given I'm increasing the tile position by 1 each time, to not hit tile 163,0 until it hits the left edge of the screen - which after all is where 0,0 is when I start. However it's not - it reports it's reached tile 163,0 when the tile is about 3 or 4 tiles away from the left hand side of the screen. That explains my 'jumping', as when I copy what I can see from a count perspective (so 163,0 to say, 220,199) to 0,0 - I never 'reached' 163,0 on the left hand side so effectively I'm skipping 3 or 4 tiles.

    I know the tile I'm trying to get to is 163,0 as I've marked it in both the map and also checked the coordinates using the tile editor.

    Hopefully that clarifies the problem a bit. I can't see any jump in the tile position when I step through it - and it's definitely moving to the left one tile at a time, so why does that tile never reach the left hand side of the screen?

    Thanks again!
     
    Last edited: Oct 27, 2015
  30. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd recommend looking at the transform.position of the camera, then move the camera back by the appropriate width when it exceeds the limit. Similar to the maxCamPosX variable in the Acorn Antics demo, which is the max camera position for the level, specifically 9 tiles in from the right. Except instead of clamping, you'd move the camera back.

    --Eric
     
  31. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Thanks Eric that helped. I think I'm (finally) there!

    Could someone just review this code (no optimisation done - just wanted to get it working!!!) and check it's on the right track - seems to work ok even when adjusting the speed (direction variable) but just want to make sure there's nothing obvious I've missed - and any comments on performance considerations always welcome.

    Thanks again - wouldn't have got this far without the help!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using SpriteTile;
    4.  
    5. public class CameraControllerv2 : MonoBehaviour
    6. {
    7.  
    8.     public TextAsset snowLevel1;
    9.     private Transform cam;
    10.     public GameObject player;
    11.     private float resetTilePosition;
    12.     private float direction = 0.1f;
    13.     float offsetValueWidth;
    14.     float offsetValueHeight;
    15.  
    16.     void Start ()
    17.     {
    18.  
    19.         Debug.Log (Screen.width + " width " + " height " + Screen.height);
    20.  
    21.         //Time.timeScale = 0.1f;
    22.  
    23.         Tile.SetCamera ();
    24.         Tile.LoadLevel (snowLevel1);
    25.         Tile.SetTileScale (1.001f);
    26.         direction = 0.35f; //Tile.GetTileSize ().x;
    27.        
    28.         // Calculate where we need to recycle the map...
    29.         // First - how many can the user see?
    30.         resetTilePosition = (Tile.GetMapSize (0).x - 14.0f) * Tile.GetTileSize (0).x;
    31.         Debug.Log ("Tile pos reset at  " + resetTilePosition);
    32.                
    33.         cam = Camera.main.transform;
    34.  
    35.         // Work out the screen middle position (for x)
    36.         // Tiles are central - so we need to offset accordingly.
    37.  
    38.         // Start in the bottom left of the map
    39.         offsetValueWidth = (Camera.main.orthographicSize * Camera.main.aspect);
    40.         offsetValueHeight = Camera.main.orthographicSize;
    41.        
    42.         cam.position = new Vector3 (offsetValueWidth, offsetValueHeight, -10f);
    43.  
    44.     }
    45.  
    46.     void Update ()
    47.     {
    48.  
    49.         var wantedPos = cam.position;
    50.         wantedPos.x = Mathf.Clamp (wantedPos.x + direction, 0.0f, 4000f);
    51.  
    52.         Debug.Log ("Position = " + cam.position.x + "," + cam.position.y);
    53.  
    54.         if (wantedPos.x > resetTilePosition) {
    55.  
    56.             Debug.Log ("Cam position resetting....adding movement and offset.");
    57.             wantedPos.x = offsetValueWidth;
    58.  
    59.  
    60.             // Work out the edge positions - that'll tell us what tiles we need to copy
    61.             var leftMostPosition = (cam.position.x + direction) - offsetValueWidth;// ((Screen.width)/100);
    62.        
    63.             var leftMostTile = Tile.WorldToMapPosition (new Vector2 (leftMostPosition, 0)).x;
    64.             var rightMostTile = Tile.GetMapSize (0).x - 1; //Tile.WorldToMapPosition(new Vector2(rightMostPosition,0));
    65.  
    66.             Debug.Log ("Left tile is " + leftMostTile + ", right most is " + rightMostTile);
    67.  
    68.             var currentMapData = Tile.GetMapBlock (new Int2 (leftMostTile, 180), new Int2 (rightMostTile, 0));
    69.             var previousMapData = Tile.GetMapBlock (new Int2 (0, 180), new Int2 (leftMostTile - 1, 0));
    70.  
    71.             // Set the map
    72.             Tile.SetMapBlock (new Int2 (0, 0), currentMapData);
    73.  
    74.             // Append the rest
    75.             Tile.SetMapBlock (new Int2 (currentMapData.mapSize.x, 0), previousMapData);
    76.         }
    77.  
    78.         cam.position = wantedPos; // Vector3.Lerp (transform.position, wantedPos, followSpring * Time.deltaTime);
    79.  
    80.  
    81.     }
    82. }
    83.  
    84.  
    85.  
    86.  
    87.  
    88.  
    89.  
    90.  
    91.  
    92.  
    93.  
    94.  
    95.  
     
  32. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Hi again,

    Well things are going much better now - I've adapted the code a bit and taken into account Time.deltaTime, and however much the map is already offset from the camera depending on the speed - and onto my next problem :)

    I can see when running it in the editor that the tile transition from one end of the map to the other is perfect - no matter how fast (or slow) I go, the tiles are moving correctly and even after switching back to the start of the map via the camera you can't see the switch - well, almost.

    The tiles are 64 x 64, I've got physics turned on for those that need it - as the tiles have slopes etc e.g. :



    Obviously the big blocks don't have either colliders or physics turned on (so roughly same area shown in the editor below) :



    So what's the problem? Well, when it's scrolling - once I get to the part I need to go back to the start, and 'switch' what's viewable back to 0,0, and the rest copied to the end of that area - I get a noticeable dip in the framerate, esp once I upload it to the phone (iPhone 5s).

    Using the profiler, I can see that it looks like the garbage collection might be causing it :

    Here's the overall picture (this is profiled from the phone, btw) :



    That big drop in frame rate is when it glitches on the phone. Here's the detail for that 'blip' :



    Which on the timeline looks like this :



    and if I zoom into the 573 items, you can see the colour corresponds with the legend for GC, and lot's of calls to clean up and reset the polygon colliders :



    All of the above is coming from this chunk of code using GetTileBlock and SetTileBlock :

    Code (CSharp):
    1. if (cam.position.x > resetTilePosition) {
    2.  
    3.  
    4.             wantedPos = originalStartPosition;
    5.  
    6.  
    7.             // Work out the edge positions - that'll tell us what tiles we need to copy
    8.             var leftMostPosition = (cam.position.x) - offsetValueWidth;
    9.    
    10.             var leftMostTile = Tile.WorldToMapPosition (new Vector2 (leftMostPosition, 0)).x;
    11.             var rightMostTile = Tile.GetMapSize (0).x - 1;
    12.  
    13.             // Work out how much of the tile is 'over' the edge of the screen boundary and add that - that should stop the skipping
    14.             var tile = Tile.WorldToMapPosition (new Vector2 (leftMostPosition, 0));
    15.             var tilePos = Tile.MapToWorldPosition (new Int2 (tile.x, tile.y));
    16.             var newOffset = leftMostPosition - tilePos.x;
    17.             wantedPos.x += newOffset;
    18.  
    19.             var currentMapData = Tile.GetMapBlock (new Int2 (leftMostTile, 180), new Int2 (rightMostTile, 0));
    20.             var previousMapData = Tile.GetMapBlock (new Int2 (0, 180), new Int2 (leftMostTile - 1, 0));
    21.  
    22.             // Set the map
    23.             Tile.SetMapBlock (new Int2 (0, 0), currentMapData);
    24.  
    25.             // Append the rest
    26.             Tile.SetMapBlock (new Int2 (currentMapData.mapSize.x, 0), previousMapData);
    27.  
    28.             cam.position =  wantedPos;
    29.  
    30.  
    31.         }
    Now I know the code is not the best - I'm just trying to tackle one bit at a time - but as the scrolling is so fundamental to the game I need to work out why it's taking so much time for the GC call, or if indeed it is that at all. The map is 64 x 64 tiles so I'm not sure if that's perhaps too small (I'm working to the iPhone 5s at the moment) given the amount of tiles potentially with colliders. I'm not sure if I should be considering larger tiles, but I did think at one point 64 x 64 might be too large (!).

    Any help with the above though would be really helpful - games are a completely new thing for me so I'm learning as I go. I normally stick with databases and web apps!

    EDIT: Hmm not sure it is GC anymore, but more the physics - I know calling GC.Collect is generally frowned upon in .net but figured I'd try some of Unity's advice on http://docs.unity3d.com/Manual/UnderstandingAutomaticMemoryManagement.html - needless to say, the spike still happens.

    EDIT: Post Eric's comments below, I turned off the physics colliders on the tiles and you can immediately see the difference :



    The time is now taken by the script, which'll just be my dodgy code. Any other stuttering I saw was caused by the profiler, so that's definitely nailed it down as the cause.

    Cheers,
    Tony
     
    Last edited: Oct 29, 2015
  33. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd suggest doing without physics colliders, if possible. Having Unity generate a bunch of polygon colliders on the fly is not all that fast, which is why SpriteTile creates all colliders for the entire level up-front. (Unlike visible tiles, which use a pooling system.) You can see that the Physics2D.PolygonColliderCreate calls take far more time than anything else. Early on I experimented with pooling colliders and it wasn't feasible, speed-wise. If it's not possible to do without physics colliders, you can try generating them a little bit at a time, as the player is moving, instead of all at once.

    --Eric
     
    PoorbandTony likes this.
  34. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    Interesting - I was thinking the same thing. To start with you'll be flying so I guess I could just use the normal colliders, and then if it's hit I guess switch them on in a block fashion when he's on the ground. Any recommendations to for that - should I turn them on per Update call, say x tiles ahead of him? Sounds like a plan, at least!

    I'll try turning off the physics first and post the results in my post above for future ref.

    Thanks again - the help on here is fantastic.
     
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd have it be time-based, rather than per Update.

    --Eric
     
    PoorbandTony likes this.
  36. PoorbandTony

    PoorbandTony

    Joined:
    Oct 7, 2015
    Posts:
    16
    I think I see what you mean. Is that best done in FixedUpdate, then?
     
  37. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    No, that's only for physics. You can use InvokeRepeating or coroutines.

    --Eric
     
  38. Eric-Gu

    Eric-Gu

    Joined:
    Feb 19, 2014
    Posts:
    28
    Excuse me, I have a question. If I create two layers with different size, I find the start point of grids on each layer will not overlap completely, even they have the same coordinate, such as Int2(0,0). There is a small gap. How can I fix this issue? Should I apply an offset on some layer. Thanks!
     
  39. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The tiles are oriented to the middle of the tiles, not a corner. You can use SetLayerPosition if you want to offset a layer.

    --Eric
     
  40. Prometheusheir

    Prometheusheir

    Joined:
    Aug 15, 2015
    Posts:
    20
    I have somehow broken my TileEditor. In the most simplest form, I now experience the following:
    - I start a new tilemap with NEW
    - I place some tiles and load the level in my game. all fine.
    - I go back to the editor, add 2 more layers, place some tiles. and load the level in my game. all fine.
    - I go back to the editor and see all my tiles, but all tiles from the first two layers are greyed out because they only show due to the "show all" option on. None of the layers still contain the tiles from these first two layers. when I flick through them they all show the tile from the 3rd (last added) layer. when I untick the "show all" option these other old tiles disapper, and flicking through all layers they are in none of them.

    Same phenomenon happens with tile size: If I add a new layer it does not take over the 0.97 value I had for the previous layer, it shows 1. and going through previous layers they now also show '1'. with such a non-1 tile size in place, the example above when loaded in game now also shows that my layers are out of sync and the tiles don't properly overlap anymore, albeit when I flick through the layers in tileeditor, the editor says tile size for all of them is 1. and changing it looks like it changes it for all in the editor, when the gameview does not change.

    I have effectively lost ability to change any but the most top layer.

    Help!

    EDIT: in a previous tilemap I may have temporarily have had more layers than I had sorting layers in Unity, which I added later. Even though I would hate for that to break my tilemap, would that also break the Editor for good with any new created maps with an allowed number of layers?
     
  41. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The editor doesn't care about the number of sorting layers; it just associates a number with each layer, though in any case the number is limited by the number of sorting layers in the project, as set by the "Set SpriteTile Sorting Layer Names" menu item.

    Anyway, I can't cause your issue to occur. Make sure you're not in play mode, and always save the level before entering play mode. If you've changed the pixel to units ratio for sprites, that could cause tiles to appear invisible (when actually they're just really huge). One limitation with the editor is that it currently assumes all layers have the same tile size when drawing other layers, so that might have something to do with what you're seeing. You can send me a PM with a link to your project if you can't figure it out.

    --Eric
     
  42. JayJennings

    JayJennings

    Joined:
    Jun 24, 2013
    Posts:
    184
    Is there something in SpriteTile that would keep me from positioning UI buttons? The following code is from my last (non-SpriteTile) game and works fine there (xPos is a calculated value):

    Code (CSharp):
    1. GameObject letterTile = (GameObject) Instantiate(letterPrefab);
    2. letterTile.transform.SetParent(canvas.transform, false);
    3. letterTile.transform.position = new Vector2(xPos, -6.5f);
    4.  
    ...but that same code doesn't work in my new SpriteTile-based game. The instantiated buttons are nowhere close to where they should be (as in, waaaaaaaay off the screen).

    I've gone back and forth from old game to new game matching up Canvas settings, etc., but haven't found anything so thought I'd see if there's something SpriteTile'ish about this kind of problem.

    Jay
     
  43. Prometheusheir

    Prometheusheir

    Joined:
    Aug 15, 2015
    Posts:
    20
    because my project is fairly advanced in other areas but not much done yet on tilemaps: in case I want to reset SpriteTile, what is the best way to do that? I have the offline version, not via Asset Store. Before I re-import the package what would I need to remove from my project?

    EDIT:

    tried a few things out and the TileEditor is definitely broken. I opened two other projects that use SpriteTile and the game itself behaves fine and displays layers correctly, however the editor will only show the settings and Tiles (as active as opposed to grey) that relate to the highest layer, no matter what layer I select. Also true for blank new projects where I add a tilemap.

    Can you please advise how to safely reinstall SpriteTile for existing projects?

    Thanks.
     
    Last edited: Nov 5, 2015
  44. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    SpriteTile doesn't touch UI stuff in any way. (It was originally made for Unity 4.3, and still works with that.) I don't think it would be possible for a 3rd-party utility to change the way Unity's UI works in any case.

    If you want to be thorough, the best way would be to start importing SpriteTile into an empty project, make note of what would be imported, and remove those things from your current project. But really, the only data stored is in SpriteTile/Resources/TileManager.asset, so that's the only file that could get broken.

    --Eric
     
    JayJennings likes this.
  45. Prometheusheir

    Prometheusheir

    Joined:
    Aug 15, 2015
    Posts:
    20
    By installing SpriteTile onto a new blank project the Editor now seems to work again in the existing project, each layer showing its own properties when selecting again. Although it did ditch all content from layer0. Odd.
    Well I will create a level now and report back in case something like this happens again.

    Thanks.
     
  46. JayJennings

    JayJennings

    Joined:
    Jun 24, 2013
    Posts:
    184
    Thanks. That, and thinking about it some more, makes me think the problem is that I'm trying to place the button in a specific location but since the camera is following my player, that location is offscreen. I need to figure out how to position the instantiated buttons based on the location of the canvas (or camera?) rather than a given location.

    Thanks.

    Jay
     
  47. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Sounds like WorldToScreenPoint is the appropriate function.

    --Eric
     
    JayJennings likes this.
  48. Eric-Gu

    Eric-Gu

    Joined:
    Feb 19, 2014
    Posts:
    28
    Thanks Eric!

    I also find another problem. Can I apply two images to transit on the same tile? I mean whether there is a way to transit the image of tile to another image. I think I need some interface, such as
    SetTile(position : Int2, layer : int = 0, tileInfo1 : TileInfo, tileInfo2 : TileInfo, transitPercent : int).
     
  49. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    What do you mean by "two images to transit on the same tile"?

    --Eric
     
  50. Prometheusheir

    Prometheusheir

    Joined:
    Aug 15, 2015
    Posts:
    20
    I was able to find out what causes the TileEditor to get corrupted, and it is reproducible:

    - start a new tilemap
    - place some tiles
    - add a new layer
    - place some tiles
    - swapping back and forth with SHOW ALL on correctly shows the active vs. grayed out tiles
    - now: click on the TILE SIZE input field, enter a number like 1.1 and while the field is still active (blue frame), switch layers.
    - from now on the TileEditor can no longer accurately display a layer's on tiles. Turn SHOW ALL off and switch between layers for example.

    If you still can't reproduce it, then I must have broken something at my end. Can send you video demonstration if you want.