Search Unity

Grids Pro: A library for hex, tri, polar and rect grids [New Dcoumentation for Grids 2]

Discussion in 'Assets and Asset Store' started by Herman-Tulleken, Jul 10, 2013.

  1. Dwel

    Dwel

    Joined:
    May 31, 2010
    Posts:
    13
    Thank you for the fixes for the polar grid Herman. It's working properly now.

    As a different type of question.

    Is it possible to alter the PolarGrid so as to give each layer an individual amount of cells (as opposed to all layers having the same amount), and how could I approach doing it?
     
  2. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hmmm interesting question that I have pondered myself.

    The short answer is, yes you can alter the polar grid like that. (It's not a built-in feature though, to be clear).

    There are two aspects to the problem. The first is just getting a grid up and running; the second is to work out a mathematical sensible way to do it so that you can solve your game algorithms easily. (The second is also optional, depending on the complexity of your game logic.)

    First Aspect
    There are three parts to it:

    Using a suitable data structure (the underlying grid). Ignoring now all niceties that could be offered by "clever" grids, I would simply base it on a rect polar or pointy brick polar grid with enough sectors to hold the largest layer. (What you give up for not being clever is the ability to iterate over points, do point arithmetic, and use any of the graph algorithms).

    Redefining the map. You will see the map functions use the variable RowsAndSectors.X to define the number of sectors for each row (the two parts of the name should probably have been swapped :---/ ). Instead, you can use an array of sector numbers, where each item corresponds to a row. The logic should be easy to modify.

    Creating a mesh. You will see in MeshUtils is a method that makes a mesh of a single row-sector. It should be easy to modify the algorithm that calls it (in the GridBuilder) to use an array of sector numbers, and calculate the correct parameters to call the mesh creation function for each row-sector.​

    This will give you a grid that can store data, be accessed with points, be rendered, and can deal with mouse input. As I said above, you cannot do point arithmetic directly, you cannot use graph algorithms (with expected results) such as path finding, and you cannot iterate over all points in the grid. The last is not so severe as it looks, you could still use a pattern like this:

    Code (csharp):
    1. foreach(var point in Grid.Where( p => p.X < sectorCounts[p.Y]))
    2. {
    3.    ...
    4. }
    Second Aspect
    The second aspect involves more work, so I would only attempt it if I were you if the algorithms of the game are fairly sophisticated.

    The idea is to be a bit more clever, and implement your grid as a "true" Grid (that is, it returns sensible values for all methods in the IGrid interface).

    Now this bit of analysis is highly dependent on how the game will work, and what types of things you want to calculate. It's hard to give you general tips off the top of my head, so instead, I can give you one example of a potential "elegant" solution.

    Before I do, let me explain how polar grids are implemented internally. The RectPolar grid is implemented as a wrapped grid, that uses a ordinary rectangular grid (in a rectangular shape) inside, and a special wrapper function to wrap points around. The circular rendering of the grid is determined by the map; it's not part of the grid itself. A polar brick grids uses a hex grid in a parallelogram shape inside the WrappedGrid. Again, the shape in which the grid is rendered is determined by the map, the grid does not "know" it's not an ordinary hex grid (except that it is wrapped along one axis).

    Now, one shape that has a growing number of cells is a triangular shape of a hex grid (presented here as a brick grid). (I am not hundred percent sure this will work as I imagine, but it should at least give you the gist of it). So imagine using this as the base, putting it in a wrapped grid, and redefining neighbors of the edges. (The circular shape is again taken care of by your map). To see how it will work, imagine that each row of the brick grid is stretched so that the shape resembles a rectangle. Now if you morph it into a circle, you get the polar grid as shown below. (Remember, this morphing is already done by the map... it's merely a way to see how the polar grid is represented internally).

    If you do everything correctly, you can now use the grid like any other. Point arithmetic gives you the cells you expect (if the wrapping is correct), graph algorithms work (if your neighbors are correct), iteration will work as normal (if your grid shape is correct).

    polar_varying.png

    (In making these images, I realized that one thing that will not work as one would want is grid colorings, which will prevent you from using certain algorithm design techniques... for example, Prim's maze generation algorithm will not work as implemented in our examples).

    Well, now that I typed it down it looks a bit intimidating. If you go this route, examine the implementation of the polar grids. It is fairly abstract, but if you can understand what is going on, you should be fine implementing the above. Also, let me know if you need help with this, or any clarification. (And remember, the first aspect is easy, and may be all you need).
     
  3. SnipersCode

    SnipersCode

    Joined:
    Jul 28, 2014
    Posts:
    3
    Thanks for answering my questions. :D

    As for my second question, I was planning on mainly 3 types of animations for my turn-based rpg.
    1) Tiles with idle animations. Ex: Idle grass "blowing in the wind" animation which would transition to an "on fire" animation if a napalm weapon was used on the tile. Or a water tile with a "waves" animation.
    2) Destructable terrain. Ex: A bomb is used on a wall, plays the "destruction" animation, and changes the type to a "hole".
    3) Range indicator. Ex. While a unit is selected and this tile is within line of sight, play a "blink red" animation or if its within movement range, "blink orange". If both, blink red then blink orange.

    The animations themselves wouldn't have to block user input because that would have been implemented by the system such that once an action has been selected, block user input, run the action, and then return control to the player.

    These were things I originally wanted to add to my game for visual effects, but as I was planning on using procedurally generated maps (was going to start with something simple like Perlin noise since there is a built in function and I just have to adjust the scale and add different functions together.), I wanted to use maps that were large (~100x100) and was thinking that a lot of animations would kill my fps. I'm ok with having a long "loading screen".
    I don't have experience in unity, so I don't know how much object pooling, loading by chunks, and dynamically changing enabled animations based on orthographic size would increase my performance.
    If I still had performance issues, I would be ok with the tiles being static.

    I was also thinking of using the built in colors and overlapping grids in Grids for terrain type and range indicators, but I don't know if having each cell check its type and set its color every frame is a good idea (which it would have to do every frame even if it hasn't changed right?).
     
  4. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    OK, so this is a big grid, that changes things a bit.

    Ignoring that for the moment, the best way is to do as you described. The basic cell design would be something like this:

    Code (csharp):
    1. class MyCell : SpriteCell
    2. {
    3.    LandscapeType landscapeType;
    4.    ActionState actionState; //Idle, Exploding
    5.    BlibkState blinkState; // Red, Orange, RedAndOrange
    6.  
    7.    LandscapeType
    8.    {
    9.       set
    10.       {
    11.          if(landscapeType != value)
    12.          {
    13.             landscapeType = value;
    14.             StartNewAnimation(); //Plays the correct animation for the current type, action state, and blink state
    15.          }
    16.       }
    17.  
    18.      ....
    19.    }
    20. }
    Two notes:
    • You do not switch animation when the value set is not different. Therefor, it is safe to set the property every frame.
    • Every animation is implemented as a Coroutine. This makes it possible to implement a state change when the action is done (for example, end of explosion), and also is (I think) the best way to implement a blink (although you could animate curves for that too...although not 100% sure it won't be slow because the color is set effectively every frame).
    Setting the color every frame for the blink would not be necessary if you do it in code. Something like this:

    Code (csharp):
    1. IEnumerator Blink(Color color, float interval)
    2. {
    3.    float timeElapsedSinceSwitch = 0;
    4.  
    5.    while(true) // you need to cancel the coroutine externally
    6.    {
    7.       while(timeElapsedSinceSwitch < interval) with this setup
    8.       {
    9.            timeElapsedSinceSwitch += Time.deltaTime;
    10.            yield return null;
    11.       }
    12.  
    13.       timeElapsedSinceSwitch -= interval;
    14.  
    15.       SetOverlayColor(Red);
    16.  
    17.       while(timeElapsedSinceSwitch < interval) with this setup
    18.       {
    19.            timeElapsedSinceSwitch += Time.deltaTime;
    20.            yield return null;
    21.       }
    22.  
    23.       timeElapsedSinceSwitch -= interval;
    24.  
    25.       SetColor(None);
    26.    }
    27.  
    28. }
    Returning now to the issue of a big grid: you may run into performance issues caused by things other than animation, in which case you may need a strategy to deal with that, which will change your system a bit. I guess you will need to see (maybe it will work fine; instantiating 100 000 cells is the slowest part; after that you may be fine). If you are not fine, then things like culling or using a single mesh come into play. (Fortunately, you won't need to change your game logic for this... But you may need to change the effects code to use sprites from your own atlas or something similar). Let me know if you want more detail on this now, or only once you get to the point and is certain it's necessary.
     
  5. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Which reminds me...

    fswipe.JPG fswipe2.JPG

    https://dl.dropboxusercontent.com/u/24097519/Fantasy Swipe/Fantasy Swipe.html
    (early version with square grid only)
    https://dl.dropboxusercontent.com/u/24097519/Fantasy Swipe v2/Fantasy Swipe v2.html
    (second version supporting irregularly shaped grids)

    You can move pieces on the board with the mouse. Pieces which move off the board will slide back in from the opposite side. If 3 or more items of the same type line up they disappear, taking any adjacent pieces of the same type with them.

    Hearts reward one HP per heart, bugs take away one HP. Gems reward one coin per pice, chests reward three. Moves without any piece getting destroyed cost one coin (unless they leave the board in the same state as before). Other items have no real functionality beyond taking up precious space. ;) At the moment there is no other goal beyond earning as many coins as possible before you run out of HP.

    The whole game logic itself is Grids only, with HOTween for smooth animation and effects. I have shelved it for now after realizing it's pretty much a clone of 10,000,000 (without even having played it before starting to work on it) but I might get back to it at some point once I have decided how to make it different enough. ;)

    (also, that background image is from Clash Of Heroes - I definitely need to replace that)
     
  6. Dwel

    Dwel

    Joined:
    May 31, 2010
    Posts:
    13
    Thank you for the information Herman, It's definitely a lot to ponder. I'm currently prototyping a design using the regular Polar Grids (same number of cells in X) and I will attempt to modify that as I begin iterating.
     
  7. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Ah nice man! It plays very smoothly; you should really think of inventing some mechanics so that you can take it further. Also, the way you did the wrapping is very cool (double rendering in + out tiles), as well as the fact that you don't necessarily wrap entire columns (if they are not connected). Did you implement a general solution that will work on all shapes? I would be interested to see how you approached this.
     
  8. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hmmm after writing it out, it seemed like it would not be so tricky to implement, so I did it. You can check out the example here:

    http://gamelogic.co.za/a-triangular-polar-pointy-brick-grid/

    triangualr_polar_grid_small.png

    It may provide you with a good starting point once you get to that phase. (This example supports almost everything. The only defect is that some cells have one, instead of two inner neighbors. This can be corrected by shifting each band increasingly as you go outwards, and removing the inner most band. ).To give you an idea of the coordinates, here they are shown in the pic below:


    coordinates_for_polar_grid.png
     
  9. Dwel

    Dwel

    Joined:
    May 31, 2010
    Posts:
    13
    Much appreciated Herman!
     
  10. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Thanks. :) The first version only worked on strictly rectangle grids but the current version is indeed working with all kind of shapes constructed out of separate rect grids. Basically all it does is taking all adjacent cells in the same line (horizontally or vertically, depending on the user's initial mouse movement) and uses them for wrapping.

    I can send you the full script once I fully understand it again and added some comments... :D
     
    Herman-Tulleken likes this.
  11. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    Is it possible to access both grid coordinates and the edge/faces of the grid? Like I want to generate a large rectangle grid and call either which grid center point is closest to a vector3 or which edge is closest? If so, how are the grid edges indexed? I was looking through the docs and didn't see anything about this.
     
  12. mbryne

    mbryne

    Joined:
    Mar 18, 2013
    Posts:
    3
    Can I also add to Fuzzy_Slippers question, in addition to edges of rectmap, how would I work out corresponding "rows", I would be interested in changing the color every x rows from north to south,

    E.g. z, x, o = alternating colours

    Code (CSharp):
    1. N zxxxoooxxxoooxxxoooz S
    2. O zxxxoooxxxoooxxxoooz O
    3. R zxxxoooxxxoooxxxoooz U
    4. T zxxxoooxxxoooxxxoooz T
    5. H zxxxoooxxxoooxxxoooz H
     
  13. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    (Sorry for taking so long to reply!)

    There is a mechanism for what you want to do. (It's available only in the full package).

    The basic idea is to use a second grid, the "edge" grid, that corresponds to the face grid. To get the edge grid of the right shape, you can call MakeEdgeGrid on your rect grid. As before, you need to populate the contents with the grid. (This is for instance useful if you want to use separate images - and cells for edges).

    This will give you a diamond grid with exactly the right cells (so what ever the shape of your rect grid, it will only have cells that correspond to edges in your original grid. You can then get the edges of a face with the method "GetEdges" that you call on a RectPoint; this will give you four diamond points. And vice versa, if you call GetEdgeFaces on a DiamondPoint, you will get the two RectPoints.

    To map points in Unity, you will need to use a Diamond map. Unfortunately, there is no automatic way provided to get the correct map, but in general, if you transform it the same as the rect map (and don't use WithWindow commands), the two maps will correspond.

    For exameple:

    Code (csharp):
    1. var faceMap = new RectMap(new Vector(100, 100))
    2.    .Translate(20, 20)
    3.    .Scale(0.1f)
    4.    .To3DXY();
    5.  
    6. var edgeMap = new DiamondMap(new Vector(141, 141))
    7.    .Translate(20, 20)
    8.    .Scale(0.1f)
    9.    .To3DXY();
    (The easiest way to make the maps match up is to use tiles which are transparent so that you can see when they overlap properly).

    There is an example for tri and hex grids (these both use rhomb grids as the edge grids) in the folder 03 TilesAsEdges.

    Let me know if I can help you more, or clarify any of my explanation.
     
  14. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    If I understand you correctly, you also want separate colors for the northern most and southernmost cells?

    Although you cannot do what you want directly using the inspector, it is straightforward to write code for this. (If you use the grid builders, just add a GridBehaviour to your component to do the coloring).

    The following scheme will give you a color from 0 to 5 for each cell, which will give you rows (that repeat every 6 rows):

    Code (csharp):
    1. foreach(var point in Grid)
    2. {
    3.     int color = point.GetColor(1, 1, 6);
    4. }
    To get to two colours, all you have to do is use floor division by 3:

    Code (csharp):
    1. foreach(var point in Grid)
    2. {
    3.     int color = point.GetColor(1, 1, 6) / 3;
    4. }
    This will give you three rows of one color, followed by three rows of the other.

    Now, to color the northern and southern edges differently, we add a check:

    Code (csharp):
    1. foreach(var point in Grid)
    2. {
    3.     int color 2; //assign edge color by default
    4.     if(!Grid.Contains(point + RectPoint.North) && !Grid.Contains(point + RectPoint.North)
    5.        color = point.GetColor(1, 1, 6) / 3;
    6. }
    Now depending on the coordinates of your grid, the pattern may "start in the wrong place" (for example, you have one edge row, two rows of one colors, then alternating rows of three colors). You just need to offset the color by some amount (you will need to play with it a bit) between 0 and 5:

    Code (csharp):
    1. foreach(var point in Grid)
    2. {
    3.     int color 2; //assign edge color by default
    4.     if(!Grid.Contains(point + RectPoint.North) && !Grid.Contains(point + RectPoint.South))
    5.        color = ((offset + point.GetColor(1, 1, 6)) % 6) / 3;
    6. }
    (These examples work with rows of three at a time, to get rows of n at a time, you can use

    Code (csharp):
    1. color = ((offset + point.GetColor(1, 1, 2*n)) % (2*n)) / n;
    Let me know if this works for you!
     
  15. mbryne

    mbryne

    Joined:
    Mar 18, 2013
    Posts:
    3
    Herman,

    Thank you for your speedy reply, I am using a pointy hex grid mapped to the surface of a cube,

    I have been able to use your color code to great effect but I have had to make an adjustment for using pointy hex points instead of rect points.

    How would I go about mapping N rows at either end? something like grid.Contains(point + PointyHexPoint.SouthWest - SomePointyHex.One) or similar? I am chasing an effect like this:

    Code (CSharp):
    1.  
    2. zzzzzzxxxoooxxxoooxxxooozzzzzz
    3.  
    Additionally, I have added an offset of 20 to the rectLeft and rectTop when mapping it to the face of the cube, if you could can you explain why that 'worked', I would love to have a calculation in there that automatically adds an appropriate offset but am at a loss as to what that would be based off, I tried rectWidth / horizontal and/or vertical cell count but was at a loss,

    I appreciate all your help so far, it's been a big learning curve so far!

    Code (CSharp):
    1.  
    2.         grid = PointyHexGrid<SpriteCell>.Rectangle(12, 29);
    3.      
    4.         Vector2 cellScale = Vector2.one * 300 * 0.0005f;
    5.         float rectWidth = board.transform.localScale.x; // 500      
    6.         float rectHeight = board.transform.localScale.z; // 1000
    7.         float rectLeft = (rectWidth / 2 * -1) + 20; //
    8.         float rectTop = (rectHeight / 2 * -1) + 20; // dat offset tho?
    9.  
    10.         map = new PointyHexMap(Vector2.one)
    11.             .AnchorCellMiddleCenter()
    12.             .WithWindow(new Rect(rectLeft, rectTop, rectWidth, rectHeight))
    13.             .Stretch(grid)
    14.             .To3DXZ((board.transform.localScale.y / 2) + 0.5f);  
    15.  
    16.         int offset = 3;
    17.         int n = 5;
    18.         foreach(PointyHexPoint point in grid)
    19.         {
    20.             SpriteCell cell = Instantiate(cellPrefab);
    21.          
    22.             cell.transform.parent = hexes.transform;
    23.             cell.transform.localScale = cellScale;
    24.             cell.transform.localPosition = map[point];
    25.  
    26.             int color = ((offset + point.GetColor(1, 1, 2*n)) % (2*n)) / n;
    27.             if((!grid.Contains(point + PointyHexPoint.SouthWest) && !grid.Contains(point + PointyHexPoint.SouthEast)) ||
    28.                (!grid.Contains(point + PointyHexPoint.NorthWest) && !grid.Contains(point + PointyHexPoint.NorthEast)))
    29.                 color = 3;
    30.  
    31.             cell.Color = ExampleUtils.Colors[color];
    32.             cell.name = point.ToString();
    33.  
    34.             grid[point] = cell;
    35.         }
     

    Attached Files:

  16. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hi mbryne!

    For this, combined with the fact that you are using hex points, I would rather just use a y-coordinate check, like this

    Code (csharp):
    1.  
    2. if((point.Y < margin) || (point.Y >= gridHeight - margin)) // if point is in margin
    3. {
    4.    color = 3;
    5. }
    6.  
    Let me know if this does the trick. (margin is an int the number of cells you want colored differently at the edges).

    Hmmm right off the top of my head I am at a loss too. Everything seems OK; it's possibly a bug. If you want, you can export me a package and mail it to me so I can have a look.
     
  17. Eldh

    Eldh

    Joined:
    Nov 22, 2010
    Posts:
    22
    Hello guys,

    So i bought Grids a while ago and i'm just starting now to mess with it. I'm not really an experienced programmer and i'm getting into some snags.
    Is it possible to animate a sprite or texture inside a grid ?
    I saw it is possible to diplay a texture inside a grid in the example with code, though all my attempts to recreate it using the editor failed. Is it even possible , to recreate the Advanced Maps example , using the editor(i'd like to have the result in front of my eyes without the need to enter play mode) ? And in the example if i extend the grid it stretched the texture, is there a way to only display the image in it's original ratio where all grid element pass the image sized are just diplaying a color ?
     
  18. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hi Eldh,

    It is indeed possible to animate sprites. Are you using Grids with a GUI package, or are you using Unity's built-in sprites?

    It is indeed possible to display an image over a grid using the editor. I had a quick go at it this morning, butt there were some unexplained offsets. Will sort it out and then post you an example.

    You can get the effect what you want as well (keeping aspect ratio); although you will need a custom map for that, which I will post with the example above.
     
  19. Eldh

    Eldh

    Joined:
    Nov 22, 2010
    Posts:
    22
    Wow that would be great ! Loogking forward to it ! I'm using unity's built in sprites.
     
  20. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hi Eldh,

    It took a bit longer than I thought, but here it is:

    http://gamelogic.co.za/grids/examples/mapping-images-to-grids-in-the-editor/

    imagemap.png

    As you will see the code is quite straightforward. We made a custom GridBehaviour to attach to the grid. This creates a new UVImageMap (very similar to ImageMap) that sets up the UV offsets and scale for each cell. There are three modes Stretch, StretchWidth and StretchHeight. The last two preserve the aspect ratio.

    Please let me know if this solves your problem!
     
  21. vToMy

    vToMy

    Joined:
    Apr 19, 2013
    Posts:
    22
    Hey,
    This package looks awesome, but before I make a purchase (want to purchase the "rect" subpackage) I'd like to make sure my requirements are met. I want to make a tile-based isometric game that looks somewhat like this album:
    http://imgur.com/a/wKa5f#0

    My concerns are the following:
    1) Will I be able to let my level designer (who doesn't know how to code) to design such a level? I saw in your videos example of grids, but all of them had the same texture, so I'm wondering how easy it is to assign different textures to grids in the inspector. Granted, as a developer I could write some helper mechanisms, so my concern is divided between how complete is the editor, and how easy it is to extend it if need arises.
    2) In the images you can see there are "layer" to the grids. Those are not so much layers as a visual effect, but I see that grids layers are only supported in the full package. Is that really the case or am I overlooking something else that I could use?

    Hoping for good news :)
     
  22. Eldh

    Eldh

    Joined:
    Nov 22, 2010
    Posts:
    22
    Hi Herman,
    Thx for the help, your package is perfect ! I know what i did wrong now. And i was able to animate the texture in the grid like i wanted using some uv animation code and some tweaks !
     
    Last edited: Aug 18, 2014
  23. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    1) You will need to implement some mechanisms to make this possible, unfortunately. (The difference in level editing for games such as Lights Out, Free Cell, and the tile game in your screenshot shows how different games are. We don't have a general solution for this problem). Grids is quite flexible, and you should have no problems impementing what you need.

    2) LayeredGrids are special 3D grids: layers of 2D grids that supports grid algorithms (such as connected lines, or path finding) in full 3D. The layers here do not refer to layers in the GUI / sprite sense. Indeed, they can only be used in the full package. However, that does not mean 2D grids cannot be layered over each other (the pattern of using a background and foreground grid is very common), and this can be done using any of our packages.
     
  24. vToMy

    vToMy

    Joined:
    Apr 19, 2013
    Posts:
    22
    Can you describe what kind of mechanisms you figured I'd have to implement (meaning are not included in the package)? No need to dive too much into detail, just an overall estimation.
    I just wanna know what I benefit and what I'd have to implement myself.

    Thanks!
     
  25. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Well, it depends on what level editing workflow you want. In terms of data; it's pretty straight forward - you basically have to implement your own cell that holds it's type and/or state, and update itself visually from that.

    When it comes to the process - i.e. how you want your level designers to edit the level - it becomes a little bit trickier, and it depends a lot on your "structure" of data as well.

    To give you an idea; suppose your cells have just a type (Road, Grass, Water) and for each type there is a single associated sprite. So you will extend your own cell from SpriteCell, add a enum for the tile type, and override the UpdatePresentation method to select the right cell from the cell type. This is the easy part.

    The most simplistic editing is to allow level designers to select the cell type, and have the sprite automatically update. To allow this, you need to implement your own editor (for your own cell), based on SpriteCellEditor that we use for SpriteCells. In this simple case, all you need to do is add the field, and make sure UpdatePresentation is still called. That is pretty much it. You will need to take care to not re-create the grid and reset all cells. (Potentially you could add functionality saving and loading levels to/from text files).

    The main thing you will gain is the algorithms, and the ability to easily implement your own in relatively terse code. The benefits for level editing (out of the box) is indeed somewhat limited.
     
  26. jimbeau

    jimbeau

    Joined:
    May 28, 2013
    Posts:
    2
    I am trying to calculate a line in my flat hex grid using only the grid itself (no map). I came across your post:

    but I see you are using the map to determine the world coordinates. I would like to do something similar, but in purely mathematical grid points. The reason for this is that I'm keeping my presentation of the grid completely separate from my logic. I want to determine a straight line between cells without having to rely on the physical representation. The physical presentation could be 3d or 2d, it really doesn't matter as long as I can get the line from the grid. To explain further, the grid is not even aware of the map, following a MVVM principle.

    I saw the link you provided (http://www.redblobgames.com/grids/hexagons/#line-drawing), and it appears this author is doing exactly what I need. I'm just not sure how to translate this into the Grids plugin.

    For simplicity, I'm assuming all cells are uniform and 1 unit along all axis, so deformities in the map don't matter.

    Any help would be appreciated!
     
    Last edited: Aug 22, 2014
  27. jimbeau

    jimbeau

    Joined:
    May 28, 2013
    Posts:
    2
    I think I figured it out. Here is the translation of the algorithm on redblobgames site into Unity / Grids:

    Code (CSharp):
    1.  
    2.   public List<FlatHexPoint> GetLine(FlatHexPoint p1, FlatHexPoint p2)
    3.   {
    4.   float q, r;
    5.   float x, y, z;
    6.   float rx, ry, rz;
    7.   float x_diff, y_diff, z_diff;
    8.   FlatHexPoint p;
    9.   int distance;
    10.   int qOffset, rOffset;
    11.   List<FlatHexPoint> line;
    12.  
    13.   distance = p1.DistanceFrom(p2);
    14.   line = new List<FlatHexPoint>();
    15.   qOffset = (p2.X - p1.X);
    16.   rOffset = (p2.Y - p1.Y);
    17.  
    18.   for (int i = 0; i <= distance; i++)
    19.   {
    20.   var t = ((float)i / (float)distance);
    21.  
    22.   q = p1.X + (qOffset * t);
    23.   r = p1.Y + (rOffset * t);
    24.  
    25.   x = q;
    26.   z = r;
    27.   y = -x - z;
    28.  
    29.   rx = (float)Math.Round(x);
    30.   ry = (float)Math.Round(y);
    31.   rz = (float)Math.Round(z);
    32.  
    33.   x_diff = Math.Abs(rx - x);
    34.   y_diff = Math.Abs(ry - y);
    35.   z_diff = Math.Abs(rz - z);
    36.  
    37.   if (x_diff > y_diff && x_diff > z_diff)
    38.   rx = -ry - rz;
    39.   else if (y_diff > z_diff)
    40.   ry = -rx - rz;
    41.   else
    42.   rz = -rx - ry;
    43.  
    44.   p = new FlatHexPoint((int)rx, (int)rz);
    45.   line.Add(p);
    46.   }
    47.  
    48.   return line;
    49.   }
    50.  
     
  28. RDeluxe

    RDeluxe

    Joined:
    Sep 29, 2013
    Posts:
    117
    Thanks for you answer, we were asking ourselves the same questions ! We are actually making a tactical game (similar to final fantasy tactic, without the elevation atm) and were looking for a solid grid system. Grids looks really good, and after testing it I really think that, on the script side, it's really what we need. However as the level designer I would like to have a easy tool to build my maps, using SpriteSheets (native Unity spritesheets, generated by TexturePacker). A good (even if not perfect) workflow would be to add several spritesheets to the Grid, and be able to change the sprite of our spritescell in few clicks, I guess this is quite possible with some basic coding. However, the save/load part is going to be necessary as I realized that this "building grid" button is going to cause me a lot of trouble :).

    Thanks for this input, really. Do you think about adding something like this anytime soon btw ?

    Edit :
    I created a CICell class following the website doc :
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using Gamelogic.Grids;
    4.  
    5. public class CICell : SpriteCell
    6. {
    7.  
    8.     //Keep states private
    9.     private bool walkable;
    10.  
    11.     //Provide public properties to change the state
    12.     public bool Walkable
    13.     {
    14.         get { return walkable; }
    15.         set
    16.         {
    17.             walkable = value;
    18.             UpdatePresentation(); //Update presentation to display new state.
    19.         }
    20.     }
    21.     private void UpdatePresentation()
    22.     {
    23.         if (this.walkable == true)
    24.         {
    25.             this.SpriteRenderer.color = new Color(0f, 0f, 0f, 1f); ;
    26.         }
    27.         else
    28.         {
    29.             this.SpriteRenderer.color = new Color(1f, 1f, 1f, 1f);
    30.         }
    31.  
    32.     }
    33. }
    And here is my custom editor code :

    Code (CSharp):
    1. using Gamelogic.Grids;
    2. using Gamelogic.Grids.Editor.Internal;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6.  
    7. [CustomEditor(typeof(CICell), true)]
    8. [CanEditMultipleObjects]
    9. public class CICellEditor : GLEditor<CICell>
    10. {
    11.     public override void OnInspectorGUI()
    12.     {
    13.         serializedObject.Update();
    14.  
    15.         var spritesProperty = FindProperty("sprites");
    16.         var walkable = FindProperty("Walkable");
    17.  
    18.         AddField(spritesProperty);
    19.         AddField(walkable);
    20.  
    21.         if (GUI.changed)
    22.         {
    23.             serializedObject.ApplyModifiedProperties();
    24.  
    25.             foreach (var t in Targets)
    26.             {
    27.                 t.__UpdatePresentation(false);
    28.                 EditorUtility.SetDirty(t);
    29.             }
    30.         }
    31.     }
    32. }
    33.  
    I have those errors popping up :
    Edit 2 : After some work, I finally decided to approach the problem differently :

    The editor class :
    Code (CSharp):
    1. using Gamelogic.Grids;
    2. using Gamelogic.Grids.Editor.Internal;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6.  
    7. [CustomEditor(typeof(CICell), true)]
    8. [CanEditMultipleObjects]
    9. public class CICellEditor : GLEditor<CICell>
    10. {
    11.     public override void OnInspectorGUI()
    12.     {
    13.         base.OnInspectorGUI();
    14.     }
    15. }
    The Cell class :
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using Gamelogic.Grids;
    4.  
    5. [System.Serializable]
    6. public class CICell : SpriteCell
    7. {
    8.     //Keep states private
    9.     [SerializeField]
    10.     private bool nonWalkable;
    11.     public bool NonWalkable
    12.     {
    13.         get { return nonWalkable; }
    14.         set
    15.         {
    16.             nonWalkable = value;
    17.             UpdatePresentation(); //Update presentation to display new state.
    18.         }
    19.     }
    20. }
    It works, I have my NonWalkable field in the editor, even if the editor view is not updated, I can set it. I guess it's not the best solution.

    Edit 3 :
    Something else which is bothering me, and I don't know yet if I have to implement a class extending the DiamongGridBuilder : our tiles are not perfectly shaped :

    This creates an interesting problem why using a XY grid (the XZ is not usable atm, we will have 3D characters and it creates depht problem while moving them around, like their feet being behind the tile). When building the grid, it's perfect, but when pressing play :


    I know this can be solved by using "layer order" but it would mean scripting this layer ordering, and I'm surprised that this is not implemented in Grids. Am I missing something ?
     
    Last edited: Aug 23, 2014
  29. tango209

    tango209

    Joined:
    Feb 23, 2011
    Posts:
    379
    Hi Herman,

    Any luck tracking down the following problem on Windows 8/8.1 development machines? I'm unable to build to any Windows target (EXE, WP8, or Store), Android, or Web Player with Grids Binary v1.9.

    The following assembly referenced from C:\Users\Robert\Documents\GridTest\Assets\Gamelogic\Plugins\Grids.dll could not be loaded:
    Assembly: UnityEditor (assemblyref_index=2)
    Version: 0.0.0.0
    Public Key: (none)
    The assembly was not found in the Global Assembly Cache, a path listed in the MONO_PATH environment variable, or in the location of the executing assembly (C:\Users\Robert\Documents\GridTest\Assets\Gamelogic\Plugins\).
     
  30. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    I am glad you solved the problem :)

    Just a few "philosophical" notes. The idea of separating grid-logic from map logic is a good one.

    In general, a problem that requires only grid coordinates should only require grid-knowledge to solve. But there is one inconvenience, and that is that grid coordinates must always be integers. And that is the only reason I used the map, to circumvent this so that we can interpolate and sample.

    Another approach would be to construct a new map, and say stretch it over the region (0, 0) [bottom left] to (1, 1) [top right] and so avoid a reference to any specific map. This map is completely hidden from the caller, and is used merely as a algebraic strut to do the calculations. I would prefer this solution, since it will keep the code short and easier to understand, but I also understand there is a bit of taste and style in the decision.
     
  31. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    I think so (we only managed to upgrade this week). I will mail you in a few minutes.
     
  32. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    We are thinking about it, although I guess for reasonable definitions of soon, it may not be soon. The more info we get, the better we can solve at least some problems. We did implement some prototype level editors, and they were so different it is still hard to know how to approach the general problem. (We should probably make those available as examples!) Thanks for posting your solutions so far as well, that is really helpful to us (to see the workflow) and I am sure for others (to see implementation strategies). Also, feel free to make specific feature requests :)

    You should not have to implement your own grid builder. What you have to do is add your own GridBehaviour, and set the order of all cells based on the value X + Y (which will give the horizontal row). More on how to do this:

    http://gamelogic.co.za/grids/docume...k-start-tutorial/working-with-gridbehaviours/

    Now that Unity finally (!) brought out the new UI, we will be giving the cells a proper design pass, and specifically look at the proper way to handle layering of overlapping cells.
     
  33. RDeluxe

    RDeluxe

    Joined:
    Sep 29, 2013
    Posts:
    117
    Thanks for your answer !

    Atm I decided to use a XZ grid and to apply a 90° rotation to my sprite :


    This works pretty well, except I'm struggling with the raycasting now (my raycasts are not at all going the right way despite being a basic stuff, so I guess I need to go back to some 3D classes ...), after solving this I should be able to get some click event working, to test the A* thing with my little character.

    I'm pretty convinced that using Grids is going to fasten our production process, I just need to get a good understanding of the plugin. (and our project is pretty special, mixing 2D tiles and 3D characters, I still have to check if we are going to be able to manage depth with the Y axis, etc).

    Do you think using Grids + this plugin is doable without too many headaches ?

    Edit : I'm also struggling with my objects ... god, this is going to be tougher than I thought !
    The solution I have found is to put my 2D objects (cars, boxes, etc) as 2D Sprites, without a rotation (so they are perpendicular to the XZ plane, like my characters) and to use the Order in Layer system , thanks to this script : http://2dtoolkit.com/forum/index.php?topic=3572.0
    Thanks to that, I'll set an "order in layer" to all my objects base on their position on the map (they are not supposed to move) and change the order in layer of my character on Update() based on their own positions.

    Edit 2 : Well, this does not work so well. First, there is the problem of big objects (sprites). Second, the characters had to have shaders without depth (Z) to be impacted by the layer system. Sadly, this is not rendering well with 3D characters.
    Our next try is going to be some hand made layer system, based on the Z position of the objects, which will be calculated the same way we did for the layers, using the map coordinates. This may work. I'll keep you updated :)
     
    Last edited: Aug 25, 2014
  34. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    What 2D system are you using? It may be a bit simpler than you think depending on what it is. (For example, if it is Unity's native 2D stuff, it may be very simple). Let me know, perhaps there is a quickfix for your problem.

    I have not had a look at that path-finding plugin. Based on it's power, I would guess it would not present you with much problems. I see from the web site they support grid-based path finding. It is in principle easy to make any other grid look like one of our grids (all you have to do is wrap their grid in a class that implements the IGrid interface), so you can then use our algorithms and coordinate systems directly.
     
  35. RDeluxe

    RDeluxe

    Joined:
    Sep 29, 2013
    Posts:
    117
    Hi Herman !
    Well, let me start over because after reading my previous messages I realize I was not clear, at all.

    Our game is a tactical RPG, using an isometric view to render the battles. Our assets are in both 2D (ground tiles, objects, etc.) and 3D (the characters and their gear). So we need to combine both, and it seems (at least for us, new to Unity and the 3D environnement in general) pretty hard.

    For a fully 2D environnement I would use the LayerOrder technique (actually explained during one Unite 2014 conference), and I thought of doing that for my 3D characters, by applying a shader without any depth (Z). It was (more or less, see next part) working, except that a non-Z shader is not an option , the texture "cannot really rotate" (it's more complicated than this) :



    So we need to use true 3D textures, which means that Unity 2D layer sorting is not working on our 3D models anymore (we need to use 3D models due to character's customization). And we don't quite know how to to this correctly.

    Another problem we have is this due to large 2D objects, as they are handcrafted.



    (i'm using a character here, but it's just as an example !)
    This last problem is pretty common to any isometric game, but we don't quite see how to solve this, except by auto-slicing (before runtime I guess) our tiles, which a pain considering our assets and to design our levels.
     
    Last edited: Aug 27, 2014
  36. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Yes, ordering issues can be a big pain (and it sometimes seem silly that it could get so complicated, even in setups simpler than yours).

    Could you use 3D for all elements, and not rely on layer order but actual depth? You will still use quads for most things, but have them positioned in space. Then, for the grid, you could use a normal grid that is flat in the XZ plane (using cells that are squares instead of diamonds), with the camera appropriately positioned and setup for orthographic rendering.

    I have not had to deal with a setup like this myself, but if you want to make me a small test scene I could have a look.
     
  37. RDeluxe

    RDeluxe

    Joined:
    Sep 29, 2013
    Posts:
    117
    So, after struggling a lot with shaders, I think that using 3D for all elements is going to be necessary.
    We are thinking about using the same strategy as ShadowRun Returns :
    We just don't quite know how to do this, and even if we can do it withing Unity itself. Still digging !
     
  38. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Does this sorting problem apply to 3D characters mixed with 2D backgrounds exclusively? I started thinking about a tiny "2D chars on 2D iso grid" project and this made me worry a bit.

    edit: While we're at it - do Grids have examples for iso grids?
     
    Last edited: Sep 4, 2014
  39. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    @barjed The issues have mostly do to with the actual shaders you use, so in principle you could solve it at a shader level.

    There is one isometric example in the 30 games project; you can send me an email then I can send you the download link: herman@gamelogic.co.za.
     
    Last edited: Sep 18, 2014
  40. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Hi Herman,

    I sent you an e-mail last week. Did you get it?

    Thanks!
     
  41. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    I did, I also sent a reply. Will resend now.
     
  42. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
  43. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Hi Herman,

    sent you a PM. Sorry for all the trouble.
     
  44. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Hi,

    it's a me again with another annoying question. I am utilizing the recently popular uFrame in my game and right now I am trying to make it work with Grids. I really liked the idea of utlizing the Grid builder, extending the class and managing all grid behaviors from there. It seemed a good match for uFrame view class but because the View themselves already extend something different, this is unfortunately impossible.

    So, is it possible to somehow utilize the builder without extending the GridBehaviours or is the way of creating a grid from code as a variable the only way?
     
  45. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hmmm, interesting.

    Out of the box, no. But you could easily make a few minor changes to make it work.

    Define an interface IGridBehaviour, with method InitGrid with the same signature as InitGrid defined in GridBehaviour. If you want, you can implement the methods defined in GridBehaviour as extension methods for GridBehaviour.

    Find the lines

    Code (csharp):
    1. var gridInitializer = GetComponent<GridBehaviour<TPoint>>();
    In TileGridBuilder and PolarTileGridBuilder, and replace them with

    Code (csharp):
    1. var gridInitializer = this.GetInterfaceComponent<IGridBehaviour<TPoint>>();
    You can now let your grid behaviours implement the IGridBehaviour interface, and have them extend from anything you want. (This is a design change we may consider doing in the future).
     
  46. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Thanks, I'll give it a try!

    Any ideas how to quickly calculate a diamond shape on a square grid, of size X? You supply a root point to the algorithm, a int range and it selects all points in a diamond shape that are within this range.

    Code (CSharp):
    1.                 var rootCells = new List<DiamondPoint> {rootCell };
    2.  
    3.                 for (var level = 0; level < BattleGrid.ParentBattle.ActiveCombatant.MovementRange; level++)
    4.                 {
    5.                     var tempCells = new List<DiamondPoint>();
    6.                     foreach (var diamondPoint in rootCells)
    7.                     {
    8.                         tempCells.AddRange(_grid.GetAllNeighbors(diamondPoint));
    9.                     }
    10.                     rootCells.AddRange(tempCells);
    11.                 }
    12.  
    13.                 var targetCells = rootCells.ToList().Distinct();
    I tried something like this but this doesn't work when the calculation touches the edge of the grid :(
     
  47. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Just to make sure, do you mean diamond shape on sqaure, alias rect grid? You can use this, where center is the center of the diamond, and the radius defines the range.

    Code (csharp):
    1. var pointsInDiamond = grid.Where( p => (p.DistanceFrom(center) <= radius));
    If you need a diamond shape on a diamond grid, you need to define a different distance metric (see http://en.wikipedia.org/wiki/Chebyshev_distance for the details), like this:

    Code (csharp):
    1. public int ChessboardDistance(DiamondPoint p, diamondPoint q)
    2. {
    3.    return Mathf.Max(Mathf.Abs(p.X - q.X) + Mathf.Abs(p.Y - q.Y));
    4. }
    That you can then use like this:

    Code (csharp):
    1. var pointsInDiamond = grid.Where(p => ChessboardDistance(p, center) <= radius);
     
  48. barjed

    barjed

    Joined:
    May 9, 2013
    Posts:
    70
    Absolutely fantastic Herman. I obviously ment Diamond Shape on a Diamond Grid but worded it poorly. Just tried your solution and it works great! Thanks!
     
    Herman-Tulleken likes this.
  49. fmarkus

    fmarkus

    Joined:
    May 22, 2010
    Posts:
    181
    Hello!
    Does the latest version work with Unity 4.6's new UI system and we can bypass NGUI on install?
    Thanks!
     
  50. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Yes it does! We have already removed the dependency on NGUI since Unity brought out the 2D tech :)