Search Unity

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,175
    No, you're not logging anything. Log all variables and data, so you know what numbers you're actually working with.

    --Eric
     
  2. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    Oh I think I see what you mean. Using this I can see which coordinates the objects are being placed, but there's still something missing, and so it's not working out the way I expect. The trigger position and the object position doesn't match, even though they are place on the same spot in the editor.

    Code (csharp):
    1.  
    2. Tile.GetTriggerPositions (6, 2, reftriggerPositions);
    3. for (vari = 0; i < triggerPositions.Count; i++)
    4.  {
    5. //varcheckPntPos = Tile.WorldToMapPosition (transform.position, 2);
    6. //Debug.Log ("Checkpoint " + checkPntPos);
    7. Debug.Log ("Checkpoint Spawns at " + triggerPositions[i]);
    8. Debug.Log ("With ID Spawns at " + Tile.WorldToMapPosition (checkPointSpawnPos.transform.position, 1));
    9. if(Tile.WorldToMapPosition (checkPointSpawnPos.transform.position, 1) == triggerPositions[i])
    10.  {
    11. Debug.Log ("CheckPoint 1");
    12. checkPointSpawnPos.GetComponent<CheckPoint>().checkpointID = 1;
    13.  }
    14. }
    15.  
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    The trigger positions are from layer 2 but the WorldToMapPosition is using layer 1.

    --Eric
     
  4. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    Right, I did that because I have the actual object being spawned using a trigger on layer 1. I'll match all the layers and see how that goes
     
  5. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    OK, so this is the entire script I'm using for placing/spawning the game objects. I hope this gives you a clearer idea of what I'm working with. Nothing seems to be working as expected.

    Code (csharp):
    1.  
    2. usingUnityEngine;
    3. usingSystem.Collections;
    4. usingSystem.Collections.Generic;
    5. usingSpriteTile;
    6.  
    7. publicclassLevelManager : MonoBehaviour
    8. {
    9.  
    10. publicGameObjectcurrentCheckPoint;
    11. publicboolcheckPointActivated;
    12. publicboolswitchActivated;
    13.  
    14. publicTransformswitchSpawnPos;
    15. publicTransformplayerSpawnPos;
    16. publicTransformredHazardSpawnPos;
    17. publicTransformcheckPointSpawnPos;
    18.  
    19. privateController2Dplayer;
    20. publicTextAssettestLevel;
    21. publicintactivatedSwitch;
    22.  
    23. Vector3playerOrigin;
    24.  
    25. List<Int2> triggerPositions;
    26.  
    27. voidAwake ()
    28.  {
    29. Tile.SetCamera ();
    30. Tile.LoadLevel (testLevel);
    31.  }
    32. //Usethisforinitialization
    33. voidStart ()
    34.  {
    35. player = FindObjectOfType<Controller2D>();
    36. GameObjectPlacement();
    37. switchActivated = false;
    38. checkPointActivated = false;
    39. //Debug.Log (currentCheckPoint);
    40. playerOrigin = player.transform.position;
    41. //Debug.Log (playerOrigin);
    42.  }
    43.  
    44. voidGameObjectPlacement ()
    45.  {
    46. Tile.GetTriggerPositions (4, 1, reftriggerPositions);
    47. for (vari = 0; i < triggerPositions.Count; i++)
    48.  {
    49. //player.transform.position = newVector2(triggerPositions[i].x, triggerPositions[i].y);
    50. playerSpawnPos.position = Tile.MapToWorldPosition (triggerPositions[i]);
    51.  }
    52.  
    53. Tile.GetTriggerPositions (2, 1, reftriggerPositions);
    54. for (vari = 0; i < triggerPositions.Count; i++)
    55.  {
    56. //switchSpawnPos.position = newVector3(triggerPositions[i].x, triggerPositions[i].y, transform.position.z);
    57. Instantiate (switchSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), switchSpawnPos.rotation);
    58.  }
    59.  
    60. Tile.GetTriggerPositions (3, 1, reftriggerPositions);
    61. for (vari = 0; i < triggerPositions.Count; i++)
    62.  {
    63. //switchSpawnPos.position = newVector3(triggerPositions[i].x, triggerPositions[i].y, transform.position.z);
    64. Instantiate (redHazardSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), redHazardSpawnPos.rotation);
    65.  }
    66.  
    67. Tile.GetTriggerPositions (1, 1, reftriggerPositions);
    68. for (vari = 0; i < triggerPositions.Count; i++)
    69.  {
    70. //switchSpawnPos.position = newVector3(triggerPositions[i].x, triggerPositions[i].y, transform.position.z);
    71. Instantiate (checkPointSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), checkPointSpawnPos.rotation);
    72.  }
    73.  
    74. Tile.GetTriggerPositions (6, 2, reftriggerPositions);
    75. for (vari = 0; i < triggerPositions.Count; i++)
    76.  {
    77. //varcheckPntPos = Tile.WorldToMapPosition (transform.position, 2);
    78. //Debug.Log ("Checkpoint " + checkPntPos);
    79. Debug.Log ("Checkpoint Spawns at " + triggerPositions[i]);
    80. Debug.Log ("With ID Spawns at " + Tile.WorldToMapPosition (checkPointSpawnPos.transform.position, 2));
    81. if(Tile.WorldToMapPosition (checkPointSpawnPos.transform.position, 2) == triggerPositions[i])
    82.  {
    83. Debug.Log ("CheckPoint 1");
    84. checkPointSpawnPos.GetComponent<CheckPoint>().checkpointID = 1;
    85.  }
    86. //if(switchSpawnPos.position == Tile.MapToWorldPosition (triggerPositions[i]))
    87. // {
    88. //switchSpawnPos.GetComponent<Switch>().switchID = 1;
    89. // }
    90.  }
    91.  
    92. //Tile.GetTriggerPositions (7, 2, reftriggerPositions);
    93. //for (vari = 0; i < triggerPositions.Count; i++)
    94. // {
    95. //if(checkPointSpawnPos.position == Tile.MapToWorldPosition (triggerPositions[i]))
    96. // {
    97. //checkPointSpawnPos.GetComponent<CheckPoint>().checkpointID = 2;
    98. // }
    99. //
    100. //if(switchSpawnPos.position == Tile.MapToWorldPosition (triggerPositions[i]))
    101. // {
    102. //switchSpawnPos.GetComponent<Switch>().switchID = 2;
    103. // }
    104. // }
    105.  
    106. Tile.SetLayerActive (1, false);
    107. Tile.SetLayerActive (2, false);
    108.  
    109.  
    110.  
    111.  }
    112.  
    113. publicvoidRespawnPlayer()
    114.  {
    115. //Debug.Log ("RespawnedPlayer");
    116. if(checkPointActivated == true)
    117.  {
    118. player.transform.position = currentCheckPoint.transform.position;
    119.  }
    120. else
    121.  {
    122. player.transform.position = playerOrigin;
    123.  }
    124.  }
    125. }
    126.  
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    I can't see any case where WorldToMapPosition wouldn't work. Unfortunately I still can't really follow what you're trying to do, or what results you're getting vs. you expect to happen.

    --Eric
     
  7. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    So what I'm trying to so is spawn checkpoints and place them where l've placed triggers in layer 1. Then using a new layer (layer 2) like you suggested, place triggers where the checkpoints would be. These layer 2 triggers would determine what ID number the checkpoints would be assigned. Right now from Tile.WorldToMapPosition (checkPointSpawnPos.position, 2) is telling me that the checkpoint is at (2,8) and I don't have any objects placed there.

    Does that make more sense?
     
    Last edited: Jul 31, 2015
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    Wouldn't you just use one loop, and assign the ID to the instantiated checkpoints right after instantiating them? I'm unclear what code like this is supposed to do:

    Code (csharp):
    1. Tile.GetTriggerPositions (4, 1, reftriggerPositions);
    2. for (vari = 0; i < triggerPositions.Count; i++)
    3.  {
    4. //player.transform.position = newVector2(triggerPositions[i].x, triggerPositions[i].y);
    5. playerSpawnPos.position = Tile.MapToWorldPosition (triggerPositions[i]);
    6.  }
    Since you're just repeatedly assigning different positions to the same object (playerSpawnPos).

    --Eric
     
  9. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    I'm using that piece of code to place the player at a designated starting point in the scene. I don't instantiate the player, I just have him in the hierarchy from the start. At least at this point.
     
  10. Nikaas

    Nikaas

    Joined:
    May 30, 2013
    Posts:
    90

    You could use the same loop to spawn your objects and assign IDs. After you spawn first object you look at the same cell position but layer2 to to get its ID and then assign that ID to the object you just spawned (all this is at same cell position/coordinates). Then the loop continues to the second object and so on.

    In other words : At layer 1 is a trigger with number that tells you code to spawn checkpoint, then at the same cell at layer 2 is its ID.
     
    Chibwemwn likes this.
  11. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    So this works, but I don't I implemented it properly. I don't know how to make sure that the correct IDs are being set to the right checkpoints. Right now the IDs are being set but I'm having spawning issues where the switches and checkpoints are being all jumbled up.

    Code (csharp):
    1.  
    2. Tile.GetTriggerPositions (2, 1, reftriggerPositions);
    3. for (vari = 0; i < triggerPositions.Count; i++)
    4.  {
    5. Instantiate (switchSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), switchSpawnPos.rotation);
    6.  
    7. Tile.GetTriggerPositions (6, 2, reftriggerPositions);
    8. for (vary = 0; y < triggerPositions.Count; y++)
    9.  {
    10. Debug.Log ("Switch 1");
    11. switchSpawnPos.GetComponent<Switch>().switchID = 1;
    12.  }
    13.  
    14. Tile.GetTriggerPositions (7, 2, reftriggerPositions);
    15. for (vary = 0; y < triggerPositions.Count; y++)
    16.  {
    17. Debug.Log ("Switch 2");
    18. switchSpawnPos.GetComponent<Switch>().switchID = 19;
    19.  }
    20.  }
    21.  
    22. Tile.GetTriggerPositions (3, 1, reftriggerPositions);
    23. for (vari = 0; i < triggerPositions.Count; i++)
    24.  {
    25. //switchSpawnPos.position = newVector3(triggerPositions[i].x, triggerPositions[i].y, transform.position.z);
    26. Instantiate (redHazardSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), redHazardSpawnPos.rotation);
    27.  }
    28.  
    29. Tile.GetTriggerPositions (1, 1, reftriggerPositions);
    30. for (vari = 0; i < triggerPositions.Count; i++)
    31.  {
    32. Instantiate (checkPointSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), checkPointSpawnPos.rotation);
    33.  
    34. Tile.GetTriggerPositions (6, 2, reftriggerPositions);
    35. for (vary = 0; y < triggerPositions.Count; y++)
    36.  {
    37. Debug.Log ("CheckPoint 1");
    38. checkPointSpawnPos.GetComponent<CheckPoint>().checkpointID = 1;
    39.  }
    40. Tile.GetTriggerPositions (7, 2, reftriggerPositions);
    41. for (vary = 0; y < triggerPositions.Count; y++)
    42.  {
    43. Debug.Log ("CheckPoint 2");
    44. checkPointSpawnPos.GetComponent<CheckPoint>().checkpointID = 19;
    45.  }
    46.  }
    47.  
     
  12. Nikaas

    Nikaas

    Joined:
    May 30, 2013
    Posts:
    90
    Forget everything you done so far. Sorry to tell you but its non sense. You should never have almost identical code repeated over and over. If you end up with something like that you done it wrong.

    Again forget everything you done so far and look at my and Eric's last posts , think it out (one single loop) and do it that way.
     
    Last edited: Jul 31, 2015
  13. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    Alright, I'll scrap everything. Now, I'm pretty new to this plug in and I'm trying to figure out how it works, I was expecting a straight forward level editor, but that's clearly not the case. My issue here is that I'm not sure how to pick and chose the layers individually, within the same loop without causing conflicts.

    Please give me an example of how you'd set up the code. I'm so confused.
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    Code (csharp):
    1. // Get trigger positions for trigger #2 on layer 1
    2. Tile.GetTriggerPositions (2, 1, ref triggerPositions);
    3. // Loop through all trigger positions
    4. for (var i = 0; i < triggerPositions.Count; i++) {
    5.     // Spawn a check point in world space for each trigger position
    6.     var spawnPos = Instantiate (checkPointSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), checkPointSpawnPos.rotation);
    7.     // Get the id from the trigger at this position on layer 2
    8.     var id = Tile.GetTrigger (triggerPositions[i], 2);
    9.     // Assign it to the instantiated check point
    10.     spawnPos.GetComponent<CheckPoint>().checkpointID = id;
    11. }
    --Eric
     
    Chibwemwn likes this.
  15. Gavriel

    Gavriel

    Joined:
    Apr 3, 2013
    Posts:
    8
    Hi,

    Can I create the sprites in runtime from scripts/code instead of using the SpriteTile editor?
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    No, the tiles need to exist in the editor.

    --Eric
     
  17. Gavriel

    Gavriel

    Joined:
    Apr 3, 2013
    Posts:
    8
    Ok, thanks, but can I at least generate the sprites at runtime and "feed" them to the editor? I don't see a specific function to this so maybe working directly with the source is the way?
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    The sprites have to exist in the project.

    --Eric
     
  19. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    So I'm getting this error message, but I don't know why it would be happening. I debug logged "spawnPos" and it returned null. I'm not sure why this is happening.

    NullReferenceException: Object reference not set to an instance of an object
    LevelManager.GameObjectPlacement () (at Assets/Scripts/LevelManager.cs:98)
    LevelManager.Start () (at Assets/Scripts/LevelManager.cs:35)
     
  20. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    It means you're trying to refer to an object that doesn't exist; I can't say any more without more info. Your best bet is to use basic debugging tactics such as logging every step, or use the debugger.

    --Eric
     
  21. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    It's strange that I'm receiving this error message, because I have checkPointSpawnPos set to a reference of an object in the inspector. I was casting the spawnPos variable as a GameObject because if I didn't I got an error from using the line

    spawnPos.GetComponent<CheckPoint>().checkpointID = id;

    The error message being:

    Assets/Scripts/LevelManager.cs(98,34): error CS1061: Type `UnityEngine.Object' does not contain a definition for `GetComponent' and no extension method `GetComponent' of type `UnityEngine.Object' could be found (are you missing a using directive or an assembly reference?)

    So I tried commenting out that line and the objects are spawned as expected. What needs to change with that last line to make it work?


    Screen Shot 2015-08-02 at 8.51.29 AM.png
     
    Last edited: Aug 2, 2015
  22. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    Use the correct type rather than Object.

    --Eric
     
  23. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    So I've tried
    Code (csharp):
    1.  
    2. varspawnPos = Instantiate (switchSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), switchSpawnPos.rotation) asGameObject;
    3.  
    but get this error
    NullReferenceException: Object reference not set to an instance of an object
    LevelManager.GameObjectPlacement () (at Assets/Scripts/LevelManager.cs:98)
    LevelManager.Start () (at Assets/Scripts/LevelManager.cs:35)


    and
    Code (csharp):
    1.  
    2. GameObjectspawnPos = Instantiate (switchSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), switchSpawnPos.rotation);
    3.  
    but get this error
    Assets/Scripts/LevelManager.cs(92,36): error CS0266: Cannot implicitly convert type `UnityEngine.Object' to `UnityEngine.GameObject'. An explicit conversion exists (are you missing a cast?)
     
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    Assuming switchSpawnPos is a Transform, you can't cast from a Transform to a GameObject.

    --Eric
     
  25. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    Okay, that solved all those issues and gave me what I expected. I changed switchSpawnPos from a Transform to a GameObject type. Then cast var spawnPos as a GameObject, and that seemed to solve it.

    Thanks so much, I appreciate all the help. Thanks for being patient with my lack of knowledge.

    Code (csharp):
    1.  
    2. //Gettriggerpositionsfortrigger #2onlayer1
    3. Tile.GetTriggerPositions (2, 1, reftriggerPositions);
    4. //Loopthroughalltriggerpositions
    5. for (vari = 0; i < triggerPositions.Count; i++)
    6.  {
    7. //Spawnacheckpointinworldspaceforeachtriggerposition
    8. varspawnPos = Instantiate (switchSpawnPos, Tile.MapToWorldPosition (triggerPositions[i]), switchSpawnPos.transform.rotation) asGameObject;
    9. Debug.Log (spawnPos);
    10. //Gettheidfromthetriggeratthispositiononlayer2
    11. varid = Tile.GetTrigger (triggerPositions[i], 2);
    12. Debug.Log (id);
    13. //Assignittotheinstantiatedcheckpoint
    14. spawnPos.GetComponent<Switch>().switchID = id;
    15.  }
    16.  
     
  26. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    A new update is out now:

    SpriteTile 2.12

    Changes:
    • Tile.LoadMapBlock can specify which layer to use, for files that have multiple layers.

    Fixes:
    • Tile.CopyGroupToPosition works if no tiles have a physics collider default.
    • If a group used with Tile.CopyGroupToPosition has any tiles with a tile number of 0, they're displayed correctly.
    • Sprites made with individual textures rather than atlases batch properly when using Unity's sprite packer.

    --Eric
     
  27. sanpats

    sanpats

    Joined:
    Aug 24, 2011
    Posts:
    343
    When will it be on asset store?
     
  28. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    As soon as they approve it; I don't have any control over that.

    --Eric
     
  29. dc5774

    dc5774

    Joined:
    Feb 1, 2014
    Posts:
    21
    Someone earlier in the thread posted about implementing Normal maps with SpriteTile sprites. Eric you mentioned using a third-party sprite-packer intead of the Unity one. Blizzy said he'd managed it. Would anyone mind elaborating on that process a little bit?

    SpriteTile is absolutely awesome by the way.

    [EDIT: extra detail] I would assume that Tile.SetMaterial() would come in handy here. I would set the mat to one that uses a bumped shader, but I have no idea how to programatically tell that shader what the sprite's normal map is.
     
  30. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    I eventually wrote my own sprite import mechanism which packs the sprites into one atlas and also tells Unity that the atlas consists of multiple sprites. In addition to that, it generates a second atlas with an identical layout that contains the normal maps. The shader does nothing special other than providing the normals from the normal maps using the UV coordinates from the SpriteRenderer.
     
    dc5774 likes this.
  31. dc5774

    dc5774

    Joined:
    Feb 1, 2014
    Posts:
    21
    Thanks blizzy, I'll go hunting for some more info on custom importing of sprites, thanks for the answer.
     
  32. Bears

    Bears

    Joined:
    Feb 7, 2015
    Posts:
    5
    Thanks for the awesome tool! I just have a quick question is there away I can load the tiles in the editor? I need to be able to create colliders around groups of the objects for our navigation system to see them. I see how I can have each tile have it's own collider but I really just need to group a large section of them together and add some scripts to it. It's becoming a pain to do this as a guessing game. Hopefully there is an easy way I can make this happen.
     
  33. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    You can use the preview function to show tiles in the scene view. However you can't attach scripts to tiles, since they exist as just a few bytes of memory. The GameObjects that are created to display tiles don't "belong" to any particular tile, but are recycled as needed, which is what allows very large levels to be fast and use a modest amount of memory. So any objects with scripts attached will need to be separate from the tilemap (but as I mentioned you can use the preview function to make it easy to position objects relative to tiles).

    --Eric
     
  34. Bears

    Bears

    Joined:
    Feb 7, 2015
    Posts:
    5
    Awesome thanks, yeah we will be making separate game objects with the collider and scripts on them. So that's not an issue just didn't know how to preview them in the editor to make the collider. Thanks for the help!
     
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    Version 2.12 is on the asset store now.

    --Eric
     
  36. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    68
    So I've run into a curious issue. Here's the code in question:

    Code (CSharp):
    1. List<Int2> triggerPositions = new List<Int2>();
    2. Tile.GetTriggerPositions(x * 10 + y, ref triggerPositions);
    3.                  
    4. Int2 pos = triggerPositions[0];
    5. Debug.Log("pos = " + pos);
    6. character.transform.position = Tile.MapToWorldPosition(pos, 1);
    This logs
    First of all, how could GetTriggerPositions possibly return a position that's out of bounds? Secondly, that should not be out of bounds by any means; the trigger I'm looking for is at that position & the map bounds are 42x31.
     
  37. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    The trigger position is from a different layer than you're using with MapToWorldPosition, so presumably the two layers have different map sizes.

    --Eric
     
  38. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    68
    Oh! You're right. I didn't even know you could do that. Thanks!
     
  39. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    I've just improved "out of bounds" error messages for future versions so they mention the layer you're operating on, which should help clarify things.

    --Eric
     
  40. G0sub

    G0sub

    Joined:
    Apr 28, 2015
    Posts:
    10
    Thanks for this, helps a ton.

    Also, I found a bug (I think) when calling SetMapTileset on a layer which contains empty tiles. In my case, the two tilesets have exactly the same number of tiles, but if any empty tiles exist in the layer, the call throws an error.

     
  41. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    You're right, sorry about that. If you want to fix it right now, use the source and in the MapData.cs file, in the SetMapTileset function, change these lines:

    Code (csharp):
    1.         for (int i = 0; i < end; i++) {
    2.             int tile = map[i] & _tileShiftI;
    To this:

    Code (csharp):
    1.         for (int i = 0; i < end; i++) {
    2.             if (map[i] < 0) {
    3.                 continue;
    4.             }
    5.             int tile = map[i] & _tileShiftI;
    --Eric
     
  42. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Did this function make it into the release? I haven't had time to check yet.
     
  43. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    No, sorry; it will be in the next version.

    --Eric
     
  44. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Thanks!
     
  45. G0sub

    G0sub

    Joined:
    Apr 28, 2015
    Posts:
    10
    Thanks for the interim fix!
     
  46. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    507
    Great asset! Saved crazy amount of work and integrates seemlessly. One thing, how do sets work? As in where are they 'stored'/referenced? I'm wanting to use SpriteTile for creating procedural dungeons, but for testing I want to use edited maps. For this I am creating a simple map and procedurally generating the tiles to display. So in the map editor I have a tileset with numbers, and place 1's for floor and 2's for walls. In the game, this map is read and another map created that replaces all the 2's with suitable wall tiles based on neighbours.

    That's the plan, but at the moment it looks like I need two tilesets with identical numbers of tiles. I don't particularly want the editing tileset available in the game as I just want the map data. In theory I could use another Unity project to edit maps and export them to my game (copy level.bytes across), but that's a bit awkward.

    So is it possible to load a set from a bunch of sprites when creating a new level? Where is set data kept?
     
  47. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,175
    The data is kept in SpriteTile/Resources/TileManager. Each set is a list of references to sprites that exist in the project; there aren't any functions for adding sprites at runtime. I'm not sure I'm 100% following what you're doing, but you can procedurally generate levels and then save them for re-use if you want (i.e., Tile.GetLevelBytes and then save the bytes using WriteAllBytes or similar).

    --Eric
     
  48. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    507
    I'm wanting to use the level editor with a different tileset with different tile count to the one used in game.
    While editing, I'll use a simplified tileset to design the level. I'll then just read the tile values and dynamically create a new level using SpriteTile and a different tileset.
     
  49. Chibwemwn

    Chibwemwn

    Joined:
    Feb 6, 2013
    Posts:
    129
    I'm setting up my camera so that as it follows the player if it reaches the limits of the level, it should stop. I'm using Tile.GetMapSize() for this, but I'm wondering if there are other tools I can use for this?

    The goal is to clamp the camera to the level bounds.
     
  50. dc5774

    dc5774

    Joined:
    Feb 1, 2014
    Posts:
    21
    I have been doing something similar with my camera controller except it's driven by player input, not a character. Here is my method for moving the camera by clicking and dragging the middle mouse button, where the user will never see the map edges. You can probably edit it so that instead of a mouse input it uses the character positions.

    I get the limit by looking at the camera's orthographic size. I'm using a TileSize of 1.0f so this maps to tile units 1:1. I'm currently overestimating the borders for simplicity, but it could easily be mathed up a bit to get the exact border size for your camera. Either way it will be some function of the camera's ortho size.

    FYI, the variables cameraPos (Vector3), orthSize (float), borderX (float) and borderY(float) are declared as class member variables in the class that calls this function so they're not re-created every frame. Remember to do this or you'll get "variable doesn't exist" type errors.

    The mapSizeX and mapSizeY could be set earlier on by Tile.GetMapSize().x and Tile.GetMapSize().y. For my game these are statics in the calling class that this method comes from (since I know my map size at the beginning).

    Code (csharp):
    1.  
    2.  
    3.      // camera controls (call this in Update)
    4.     void MapScroll () {
    5.  
    6.         // update camera positon and ortho size
    7.         cameraPos = Camera.main.transform.position;
    8.         orthSize = Camera.main.orthographicSize;
    9.         borderX = orthSize * 2.5f;
    10.         borderY = orthSize * 1.1f;
    11.  
    12.         // map move (click and drag)
    13.         if(Input.GetMouseButton(2))
    14.         {
    15.             // get input
    16.             float x = Input.GetAxis("Mouse X") * -1f;
    17.             float y = Input.GetAxis("Mouse Y") * -1f;
    18.  
    19.             // set x input to 0 if outside of x borders
    20.             x = (cameraPos.x < borderX && x < 0) ? 0 : x;  // if its on the left and you're trying to move left  
    21.             x = (cameraPos.x > mapSizeX - borderX && x > 0) ? 0 : x; // if its on the right and you're trying to move right
    22.  
    23.             // set y input to 0 if outside y borders
    24.             y = (cameraPos.y < borderY && y < 0) ? 0 : y;   // if it's on the bottom and you're trying to move down
    25.             y = (cameraPos.y > mapSizeY - borderY && y > 0) ? 0 : y; // if its on the top and you're trying to move up
    26.  
    27.             // move the camera
    28.             Camera.main.transform.Translate(x,y,0);
    29.         }
    30.  
    31.     }
    32.  
    33.  
    [Edit: some typos in the code comments]
     
    Last edited: Aug 13, 2015