Search Unity

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

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. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Thanks for letting us know. It should be sorted now :)
     
  2. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
  3. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358

    I am not sure I understand your first question. The algorithm will only consider points that are part of the grid in the first place, so it is not meant to filter out points that are not part of the grid. It is meant to filter out specific cells, and we made the assumption that that information is usually a property of the cells. If this is not the case for you, we would love to see an example (this may compel us to provide this functionality).

    Cells do not know their grid positions. This was a deliberate decision, as well believe that if cells had access to this information, it would lead to brittle designs. IGrid<TCell, TPoint> does have the accesors, but not IGrid<TPoint>. The path finding algorithms use IGrid<TCell, TPoint>, so are you talking about another case? Let me know which, and what you want to do, then I can suggest the "best practice" solution. (A not-necessarily-best-practice solution is to cast the grid to IGrid<TCell, TPoint>. If, however, this was a good solution, we would have used the more specific interface... so I assume there is a better way to go about it).
     
  4. Aggressor

    Aggressor

    Joined:
    Aug 10, 2012
    Posts:
    62
    So for the accessor error:

    private IGrid<GridCell, PointyHexPoint> _grid;

    However if I try to do _grid[pointyHexPoint] I get the compiler error:

    Cannot convert type 'GridCell' to 'Gamelogic.Grids.PointyHexPoint'

    Regarding the design choice:

    As I have it currently, my GridManager looks for click events and keeps track of where the units are positioned. So my thought process was it only makes sense for this also check if a cell is available. When the pathfinder goes looking, I think the isCellAvailable function should call the GridManager, and it checks to see if the points are available, if so, then it can move, otherwise no go.

    But I am more than happy to do it the better way if you could elaborate. My thoughts would be cells shouldnt really know anything, even being accessible seems like another classes job, or am I missing out?
     
  5. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hmmm from that error it looks like either pointyHexPoint is not in fact a PointyHexPoint, but a GridCell, or you are assigning _grid[pointyHexPoint] to a PointyHexPoint variable or parameter. Check the declaration of pointyHexPoint, and check carefully what you do with the result of _grid[pointyHexPoint].

    I understand your use case: essentially you are maintaining accessibility centrally, which makes sense when this data changes often (so maintaining it separately in a cell is a bit tricky) and the units are relatively sparse in the grid. This is something we will think about for the future, it's an interesting case and I am actually surprised it did not come up before.

    For now, the two solutions I can see is to maintain the data in the cells, or make an additional path-finding method that uses the point instead of cell (Func<TPoint, bool> isAccessible) by just duplicating our method and making the (very small) change. The last one seems to me the kind of change we could make, so it will anticipate a future library change (although no guarantees!). If you go this route, it would be helpful if you could let us know how it goes.
     
    Aggressor likes this.
  6. Aggressor

    Aggressor

    Joined:
    Aug 10, 2012
    Posts:
    62
    If I can get the cell converting to a point its really a non issue I suppose to. Once I have the point I can do the check myself. I was just running into a snag getting the point from a cell. Will look into this tonight thanks.
     
  7. AwDogsGo2Heaven

    AwDogsGo2Heaven

    Joined:
    Jan 17, 2014
    Posts:
    102
    Does this work with iOS when using iL2CPP?
     
  8. JellyfishUmbrella

    JellyfishUmbrella

    Joined:
    May 6, 2015
    Posts:
    5
    Hi, I am trying to make a very VERY large hex grid which is too big to fit into one mesh. I've broken it up into smaller, more easily renderable chunks to make this work, and to aid in updating the world without lagging the system down. The master grid will hold the cell data, do the pathfinding etc. The render chunks will reference the master grid to determine what they need to look like.

    Because you can't subdivide a hexgrid evenly like you can a square grid, there were always some extra renderable hexes sticking out beyond the edges of the big master grid. So I'm now trying to approach the problem from the other way around. I want to be able to lay out my render chunks, and have the master grid match that. The way the shape Ops work however is strange to me and I'm having a hard time grokking just how to go about this correctly.

    In this first picture, you see a small version of the render chunks.
    renderGrids.jpg
    The bright red line is supposed to show the structure grid I create like this:
    Code (csharp):
    1.  
    2.         structureGrid = PointyHexGrid<MeshedPointyGridMap>.Hexagon (subDLevel);
    3.         structureMap = new PointyHexMap(PointyHexDimensions)
    4.                                                       .AnchorCellMiddleCenter ()
    5.                                                       .Rotate(90)
    6.                                                       .Scale (structureRadius);
    7.  
    At each point in structureGrid (7 in this example, but I will ultimately use many more), I build a smaller grid with pointy hexes feeding a mesh so they render.

    My thought was that I could also use the structure grid to place hexagons which I can union together into a shape for the bigger master grid.

    But using this code:
    Code (csharp):
    1.  
    2.     public PointyHexGrid<PointyHexFace> getDataGridShape(float Diameter_PerHex){
    3.  
    4.         PointyHexOp<PointyHexFace> shape = PointyHexGrid<PointyHexFace>.BeginShape ();
    5.         PointyHexShapeInfo<PointyHexFace> shapeInfo = shape.Default(0,0);
    6.  
    7.         foreach (PointyHexPoint point in structureGrid) {
    8.                 shapeInfo = shapeInfo.Union().Hexagon(MaxRenderGroupHexRadius).Translate (point.X, point.Y);
    9.         }
    10.  
    11.         return shapeInfo.EndShape();
    12.     }
    13.  
    I get this (Where the darker grey is the master grid - normally it won't render since it'll be too big).:
    renderGrids_2b.jpg
    Obviously, I'm not translating the shape properly.


    But taking out the .Translate(point.X, point.Y) bit still gives me this:
    renderGrids_2.jpg
    When I would expect all the shape hexes to sit on top of each other.

    Is there an easier way to do this, or am I going to have to unravel all the offsets myself? Because trying to do that just leads me to this:
    renderGrids_2a.jpg

    Thanks,
    -Rich
     
  9. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    In theory, it should work. However, we had one user report a problem, and given that even the standard mono compiler Unity uses cannot generate correct code in all cases, it seems that in practice there may be some issues. We will spend the next two days or so thoroughly investigating the issue, and will get back to you here.
     
  10. Herman-Tulleken

    Herman-Tulleken

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

    This is an interesting problem, and there are several overlapping issues.

    Your intuition about union and translate is correct, the method should work. Now it's possible that something small is wrong somewhere, or you uncovered a bug. (The code for the shape ops is unbelievably complex, and bugs are extremely subtle.) It would be helpful if you could mail me a test package so that I can investigate it some more.

    I am trying to understand exactly what you are trying to accomplish. On the face if it, it seems like you want a low res grid, each cell which is made up of a grid of smaller cells (that happen to connect smoothly), and a high res grid which corresponds (in shape) exactly to the chunks of the low res grid.

    One alternative way to do it is to have a function: HighResToLowRes which takes a point, and give you the low res point. You can then construct a test function like this:

    Code (csharp):
    1. bool IsInHighResGrid(highResPoint)
    2. {
    3.    return lowResGrid.Contains(HighResToLowRes(highResPoint);
    4. }
    You can then make your grid using a constructor, rather than the shape ops. All you have to do is calculate the right size for the grid, and the right offset, and feed this together with the test function above and you are good. (It will probably be best to look at how the hex shape is implemented to work out the right offset and size, since your shape will be contained within a hex shape as long as it is large enough).

    (The union operations are possibly not suitable for joining large number of chunks - we have never tested this in the wild).

    So this leaves the HighResToLowRes function, which can be somewhat tricky to implement.

    You can look at this example, were we have done exactly this:

    http://gamelogic.co.za/2014/06/17/cloudy-noise-on-a-hex-grid/

    To follow the mathematics is a bit tricky. But it uses operations that are similar to what are used for subdividing rect grids that should be familiar to you. Every point can be written in this form:

    P = Q MUL n + R

    Where Q and R are points, and MUL is some abstract operation which corresponds to multiplication for rect grids. For example,

    (14, 10) = (4, 3) MUL 3 + (2, 1) //// for rect grids

    We can also write

    P DIV n = Q

    and

    P MOD n = R

    Now hex points have analogous operations, although they are not so neatly calculated. In our example, we implemented a function Div2, which corresponds to dividing a hex grid into chunks of 7 hexes each (the same way as in your example):

    screen_445.png
    (You should be able to use the implementation we provide as is. If you want to understand where the formulas there comes from, let me know.)

    By re-applying this function, you can get definitions for DIV 4, DIV 8, etc. which gives you bigger and bigger chunks:

    screen_446.png screen_449.png

    You may also want to think of using parallelograms instead of hexi-like shapes, which works exactly like the rect case, and are therefor much easier to work with. Also, is there a reason you need a full highres grid in the first place? Would a grid of grids not work too?
     
    Last edited: May 14, 2015
  11. JellyfishUmbrella

    JellyfishUmbrella

    Joined:
    May 6, 2015
    Posts:
    5
    Yes, I'd seen the hexgrid perlin noise example you guys had done a little while ago, but I was trying not to over-complicate things. Haha, too late! Something along those lines will probably be my next attempt.

    Ultimately, what I'm aiming for is a gigantic hex grid based terrain that is dynamic to a limited degree (only small bits need to be updated at any one time). I started with a super big grid but ran into the 65000 vertex limit fairly quickly, so I'm trying different ways of breaking it up into renderable chunks, hopefully without too many overlapping hexes, or extraneous bits of render hexes that aren't contained within the data grid.

    And this is just the world map. Once I get this part working to my satisfaction, I want to take each hex of the big data grid, and be able to dynamically subdivide it even further to provide a local area the player can walk around in. On the big data grid, a road (for example) could take up an entire hex. On the local area grid representing that one data hex, that road might be three or four hexes wide, and meander about through individual trees and rocks and things that wouldn't be directly represented on the big map. So there will be multiple layers of grid-resolution, with certain things (people-scale details) only working at the local, high-resolution level, and others (like roads and erosion) on the low-resolution full map.

    Grids has already helped me to quickly get to the point where I've realized that my first few ideas of how to build what's in my head were pretty poorly thought-out. Even though I've built and rebuilt this mapping part of things at least four times already, I've made some informative mistakes along the way. It's been a good way to teach myself Unity and C#.

    Thanks for looking into this and giving me some suggestions. I know I'm not the only one who appreciates how open and accessible you are to those of us needing help.

    -Rich
     
  12. Jonathan-Bailey

    Jonathan-Bailey

    Joined:
    Aug 12, 2013
    Posts:
    79
    Grids Lite is now available for free

    GridsLite680x340.png

    Hi Everyone,


    Just a heads up that you can now pick up Grids Lite for free in the Asset Store (it was $20 before). You can Download it here.

    (In case you didn't already know) Grids Lite allows you to rapidly prototype and develop your games using Rect, Diamond and certain Polar grids. It contains many algorithms, including A* path-finding, range-finding and connection algorithms (used in match games).

    You can get more info about Grids here or compare Grids Lite its features with Grids Basic and Grids Pro here.

    Edit: This offer has expired.
     
    Last edited: Sep 8, 2015
  13. Nitroflight

    Nitroflight

    Joined:
    Aug 19, 2011
    Posts:
    1
    Do you have a Unity 5 version of this Asset? I would like to buy it.
     
  14. JK_Aahz

    JK_Aahz

    Joined:
    Jun 13, 2013
    Posts:
    6
    Herman-Tulleken likes this.
  15. Alphalpha

    Alphalpha

    Joined:
    Oct 9, 2013
    Posts:
    74
    I second this. It's definitely one of the more striking demonstrations of the package, and something I'm currently interested in experimenting with.
     
    Herman-Tulleken likes this.
  16. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    The current version works with Unity 5. The Asset Store gives a warning because we did not upload the package with Unity 5. We did submit packages published from Unity 5 this week, and these should be in the store soon. (We submitted both Unity 4 and Unity 5 packages, and they are exactly the same, so Unity 4 users don't have to worry!)
     
  17. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
  18. piotrO

    piotrO

    Joined:
    Dec 16, 2009
    Posts:
    46
    Hi Herman,

    1) Is there a way to set a maximum path size in the AStar algorithm?

    For example if unit has just 4 movement points the algorithm would not search for paths with more than 4 path nodes.

    Right now for small grids the AStar works just fine, but when we have bigger grids the pathfinding takes a lot of time to compute - creating a noticeable lag.

    2) I need to generate a pointy hex shaped grid, and there is just a flat hex shape available in your library. Any tips how to generate a pointy hex shape?

    Thanks,
    Piotr
     
  19. Herman-Tulleken

    Herman-Tulleken

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

    1) I was gonna say yes, and as I typed the example, I realised it is in fact not possible at the moment. It would be simple if the IsAccessible parameter was Func<TPoint, bool> instead of Func<TCell, bool>. Another user also asked for this functionality, so I think we will probably put it in.

    For now, you can add the following function to Algorithms:

    Code (csharp):
    1. public static IEnumerable<TPoint> AStar<TCell, TPoint>(
    2.     IGrid<TCell, TPoint> grid,
    3.     TPoint start,
    4.     TPoint goal,
    5.     Func<TPoint, TPoint, float> heuristicCostEstimate,
    6.     Func<TPoint, bool> isAccessible,
    7.     Func<TPoint, TPoint, float> neighborToNeighborCost)
    8.  
    9.     where TPoint : IGridPoint<TPoint>
    10. {
    11.     var closedSet = new HashSet<TPoint>(new PointComparer<TPoint>());
    12.  
    13.     // The set of tentative nodes to be evaluated
    14.     var openSet = new HashSet<TPoint>(new PointComparer<TPoint>()) { start };
    15.  
    16.     // The map of navigated nodes.
    17.     var cameFrom = new Dictionary<TPoint, TPoint>(new PointComparer<TPoint>());
    18.  
    19.     // Cost from start along best known path.
    20.     var gScore = new Dictionary<TPoint, float>(new PointComparer<TPoint>());
    21.     gScore[start] = 0;
    22.  
    23.     // Estimated total cost from start to goal through y.
    24.     var fScore = new Dictionary<TPoint, float>(new PointComparer<TPoint>());
    25.     fScore[start] = gScore[start] + heuristicCostEstimate(start, goal);
    26.  
    27.     while (!openSet.IsEmpty())
    28.     {
    29.         var current = FindNodeWithLowestScore(openSet, fScore);
    30.  
    31.         if (current.Equals(goal))
    32.         {
    33.             return ReconstructPath(cameFrom, goal);
    34.         }
    35.  
    36.         openSet.Remove(current);
    37.         closedSet.Add(current);
    38.  
    39.         var currentNodeNeighbors = grid.GetNeighbors(current);
    40.  
    41.         var accessibleNeighbors = from neighbor in currentNodeNeighbors
    42.                                     where isAccessible(neighbor)
    43.                                     select neighbor;
    44.  
    45.         foreach (var neighbor in accessibleNeighbors)
    46.         {
    47.             var tentativeGScore = gScore[current] + neighborToNeighborCost(current, neighbor);
    48.  
    49.             if (closedSet.Contains(neighbor))
    50.             {
    51.                 if (tentativeGScore >= gScore[neighbor])
    52.                 {
    53.                     continue;
    54.                 }
    55.             }
    56.  
    57.             if (!openSet.Contains(neighbor) || tentativeGScore < gScore[neighbor])
    58.             {
    59.                 cameFrom[neighbor] = current;
    60.                 gScore[neighbor] = tentativeGScore;
    61.                 fScore[neighbor] = gScore[neighbor] + heuristicCostEstimate(neighbor, goal);
    62.  
    63.                 if (!openSet.Contains(neighbor))
    64.                 {
    65.                     openSet.Add(neighbor);
    66.                 }
    67.             }
    68.         }
    69.     }
    70.  
    71.     return null;
    72. }
    It works exactly the same as the existing one, except that the IsAccessible parameter takes a function with parameter TPoint, not TCell.

    You can now limit the range as follows:

    Code (csharp):
    1. var path = Algorithms.AStar(
    2.    grid,
    3.    start,
    4.    goal,
    5.    HeuristicCost // whatever you used before
    6.    p=> p.DistanceFrom(goal) <= range && IsCellAccessible(grid[p]) //the last part can be whatever you had before
    7.    ActualNeighbirToNeighborCost //whatever you had before
    8.    );
    9.  
    Let me know if this works for you (and whether it gives you the necessary speedup).

    Edit: I see the function can cause problems with ambiguous invocation of existing code in the examples. The easiest way to get around this for now is to just give the function a different name. EndEdit

    2. What licence do you have, and are you using the newest version? You should have both hex versions (except if you have the Lite licence). (It's possible that we made a mistake in one of the packages). Or do you mean the actual shape of the grid (how the cells are arranged)? If so, could you send me a picture of exactly what you mean?
     
    Last edited: May 23, 2015
  20. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Here is another approach. It is not better than the one above, but it shows some important concepts when working with grids, and it is very easy to extend the ideas to get more power and flexibility.

    The basic idea is to use a window into your main grid, in this case limited by the distance from the start. This window is a grid itself (in that it implements the IGrid<TCell, TPoint> interface, and thus it can be used with all the algorithms that work on IGrids.

    You will have to create the grid window, and to start with, you just give it a function that does not limit the window, so it resembles the original grid. It should be a field of your class, so that you can just update the contains function.

    Code (csharp):
    1. gridWindow = new GridWindow(grid, p=> true);
    The path finding call can then be:

    Code (csharp):
    1. gridWindow.ContainsFunc = p=> p.DistanceFrom(start) < range;
    2. var path = (
    3.    gridWindow,
    4.    start,
    5.    goal,
    6.    HeuristicCost // whatever you used before
    7.    IsCellAccessible(grid[p]) //whatever you had before
    8.    ActualNeighbirToNeighborCost //whatever you had before
    9.    );
    And here is the vanilla definition of grid window:

    Code (csharp):
    1. public class GridWindow<TCell, TPoint> : IGrid<TCell, TPoint> where TPoint : IGridPoint<TPoint>
    2. {
    3.     public Func<TPoint, bool> ContainsFunc
    4.     {
    5.         get;
    6.         set;
    7.     }
    8.  
    9.     private IGrid<TCell, TPoint> grid;
    10.  
    11.     public GridWindow(IGrid<TCell, TPoint> grid, Func<TPoint, bool> containsFunc)
    12.     {
    13.         this.grid = grid;
    14.         ContainsFunc = containsFunc;
    15.     }
    16.  
    17.     public bool Contains(TPoint point)
    18.     {
    19.         return ContainsFunc(point) && grid.Contains(point);
    20.     }
    21.  
    22.     public IEnumerator<TPoint> GetEnumerator()
    23.     {
    24.         return grid.Where(point => ContainsFunc(point)).GetEnumerator();
    25.     }
    26.  
    27.     IEnumerator IEnumerable.GetEnumerator()
    28.     {
    29.         return GetEnumerator();
    30.     }
    31.  
    32.     object IGrid<TPoint>.this[TPoint point]
    33.     {
    34.         get { return this[point]; }
    35.         set { this[point] = (TCell) value; }
    36.     }
    37.  
    38.     public TCell this[TPoint point]
    39.     {
    40.         get
    41.         {
    42.             if (Contains(point))
    43.             {
    44.                 return grid[point];
    45.             }
    46.  
    47.             throw new ArgumentOutOfRangeException("point", "not in grid");
    48.         }
    49.         set
    50.         {
    51.             if (Contains(point))
    52.             {
    53.                 grid[point] = value;
    54.             }
    55.             else
    56.             {
    57.                 throw new ArgumentOutOfRangeException("point", "not in grid");
    58.             }
    59.         }
    60.     }
    61.  
    62.     public IEnumerable<TPoint> GetAllNeighbors(TPoint point)
    63.     {
    64.         return grid.GetAllNeighbors(point);
    65.     }
    66.  
    67.     public IGrid<TNewCell, TPoint> CloneStructure<TNewCell>()
    68.     {
    69.         var clonedGrid = grid.CloneStructure<TNewCell>();
    70.         return new GridWindow<TNewCell, TPoint>(clonedGrid, ContainsFunc);
    71.     }
    72.  
    73.     public IEnumerable<TPoint> GetLargeSet(int n)
    74.     {
    75.         return grid.GetLargeSet(n);
    76.     }
    77.  
    78.     public IEnumerable<TPoint> GetStoragePoints()
    79.     {
    80.         throw new NotSupportedException();
    81.     }
    82.  
    83.     public IEnumerable<TCell> Values
    84.     {
    85.         get { return grid.Where(p => ContainsFunc(p)).Select(p => grid[p]); }
    86.     }
    87.  
    88.     IEnumerable IGrid<TPoint>.Values
    89.     {
    90.         get { return Values; }
    91.     }
    92. }
    Grid windows are useful in other contexts too; for example, if you wanted to render only a part of your grid. Depending on how you use it, you can implement some optimisations. For example, if you need to iterate over all points of the window, and you do this (way) more than updating the contains func, you can cache the points in the window.

    Like I said, this approach is not better if the one in the previous post works fine, but it gives some ideas of what else is possible.
     
  21. piotrO

    piotrO

    Joined:
    Dec 16, 2009
    Posts:
    46
    Thanks for your indepth reply.

    1) It turned out the lag was caused by something else (fog of war code) - and your hint about the Grid Window helped to resolve that other issue. So in other words the Grid's AStar implementation works well even on bigger maps out of the box.

    2) Yes I meant the actual shape of the grid. Right now I generate my grid like this:

    Code (csharp):
    1.  
    2. PointyHexGrid<TileCell>.Hexagon(6);
    3.  
    And I need something like:
    Code (csharp):
    1.  
    2. PointyHexGrid<TileCell>.PointyHexagon(6);
    3.  
    In order to get a grid shaped like a pointy hex.

    I have Basic and Lite licenses.
     
  22. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    1) Glad to hear you solved it!

    2) Do you mean like the shapes in this image:

    Grid-Hex.png

    If so, here is how you can get that shape:

    Add the following function to the AbstractShapeInfo class:

    Code (csharp):
    1.  
    2. public TShapeInfo Filter(Func<TPoint, bool> filter)
    3. {
    4.     Func<TPoint, bool> newIsInside =
    5.         x => shapeStorageStorageInfo.contains(x) && filter(x);
    6.  
    7.     var newStorageRect = shapeStorageStorageInfo.storageRect;
    8.  
    9.     return MakeShapeInfo(new ShapeStorageInfo<TPoint>(newStorageRect, newIsInside));
    10. }
    (This is a function that I've been wanting to add for some time, and it will be in the next update.)

    You can then build your grid with the following:

    Code (csharp):
    1. PointyHexGrid<TCell>
    2.     .BeginShape()
    3.     .Hexagon(2*size - 1)
    4.     .Filter(p => Rotate30(p).Magnitude() < (3.5f * size - 3) * Mathf.Sqrt(3) / 2)
    5.     .EndShape();
    where Rotate30 is defined as follows:

    Code (csharp):
    1. private PointyHexPoint Rotate30(PointyHexPoint p) //rotated, but also scaled
    2. {
    3.     return new PointyHexPoint(p.X - p.Y, p.X + 2 * p.Y);
    4. }
    You can also define your own CustumGridBuilder to use with a GridBuilder like this:

    Code (csharp):
    1. public class PointyHexShape : CustomGridBuilder
    2. {
    3.     public int size = 1;
    4.     public override IGrid<TCell, TPoint> MakeGrid<TCell, TPoint>()
    5.     {
    6.         if (typeof (TPoint) != typeof (PointyHexPoint))
    7.         {
    8.             throw new Exception("This script can only be used with PointyHexGrids");
    9.         }
    10.  
    11.         return (IGrid<TCell, TPoint>) PointyHexGrid<TCell>
    12.             .BeginShape()
    13.             .Hexagon(2*size - 1)
    14.             .Filter(p => Rotate30(p).Magnitude() < (3.5f * size - 3) * Mathf.Sqrt(3) / 2)
    15.             .EndShape();
    16.     }
    17.  
    18.     private PointyHexPoint Rotate30(PointyHexPoint p)
    19.     {
    20.         return new PointyHexPoint(p.X - p.Y, p.X + 2 * p.Y);
    21.     }
    22. }
    23.  
    To understand why this works is a little tricky, but here is the gist:

    "Normal" (flat) hex shapes are defined by a magnitude check (similar to disks in normal Euclidean 2D), but we want one that is pointy, so we rotate by 30 degrees. To derive the formula for a 30 degrees turn, we take the square root of the matrix M that rotates a point by 60 degrees. This gives a matrix with non-integer values. Fortunately, we can multiply with a constant factor (2 / sqrt(3)) to have integers points, as long as we modify our radius of the check accordingly.

    Up to this point we also get some other pointy shapes, such as the one below. They fall between the "right" ones, and we can eliminate them by some more scaling and offseting - this is the (3.5f * size - 3) factor, which I determined with trial and error.

    hex1.PNG
     
    Last edited: May 24, 2015
  23. piotrO

    piotrO

    Joined:
    Dec 16, 2009
    Posts:
    46
    Perfect! You're awesome!
     
  24. Jonathan-Bailey

    Jonathan-Bailey

    Joined:
    Aug 12, 2013
    Posts:
    79
    Support Upgrade

    Hi Everyone,

    We have upgraded our support system to make responding to your queries faster and more efficient.

    There are two parts to the upgrade.


    Support email – Zendesk

    We are now using Zendesk to handle our support email. Tickets are created for each email that we receive at support@gamelogic.co.za. With Zendesk we are able to track and monitor each ticket to make sure that your questions are always resolved.

    Knowledge Base – Quandora

    Quandora is a Q & A forum where you can search for already answered questions about our products. And if you can’t find an answer for what you are looking for, you can post a new question which will be answered either by one of us or by one of our community members.

    If you have any questions about the upgrade, you know what to do :)
     
  25. Jonathan-Bailey

    Jonathan-Bailey

    Joined:
    Aug 12, 2013
    Posts:
    79
  26. movra

    movra

    Joined:
    Feb 16, 2013
    Posts:
    566
    I take it that upgrade deal doesn't apply to those who picked up Grids Lite for free a month ago, right? ;)
     
  27. Jonathan-Bailey

    Jonathan-Bailey

    Joined:
    Aug 12, 2013
    Posts:
    79
    It actually does :) You should be able to upgrade straight from the asset store page.
     
    movra likes this.
  28. movra

    movra

    Joined:
    Feb 16, 2013
    Posts:
    566
    Wow, in that case, what an amazingly generous offer!

    I can see the upgrade price, but I don't know how I can take advantage of it.



    I didn't get a receipt when I added Grids Lite to my account, probably because it was free, but it does show up in my Packages library.



    I think the asset store upgrade system does a check against the purchase history, and free assets don't show up in there. Although the monthly free Level 11 assets do show up as well as assets acquired through vouchers.
     
    Last edited: Jun 24, 2015
  29. Jonathan-Bailey

    Jonathan-Bailey

    Joined:
    Aug 12, 2013
    Posts:
    79
    We've done a few tests and it appears that Unity doesn't let you upgrade from a free product to a paid one :( But send me an email at jonathan@gamelogic.co.za and we can sort you out.
     
    movra likes this.
  30. apocriva

    apocriva

    Joined:
    Nov 3, 2011
    Posts:
    25
    Any recommended approach to get Grids working with the new Unity Networking that was added in 5.1?
     
  31. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    I must admit that I have no idea how the new networking works (yet!) So I cannot say at all what will be involved.

    One thing to keep in mind is that Grids are essentially like arrays; except for their contents, they have no state. So once they are built, you just have to make sure that grids content's are synched up. So - at least in principle - anything you do to keep arrays in synch over a network can be done for grids too. (And if Unity has some magic for arrays, we could potentially hook grids into that, since that is what lies underneath grids).

    Once I have had a look at the networking I can of course give a more accurate answer. In the meantime, it would be helpful if you could give a more detailed description of what you would like to do.
     
  32. mkgame

    mkgame

    Joined:
    Feb 24, 2014
    Posts:
    592
    Hello,

    the second time a see this asset in 24 hour sales, but i still don't know what is in the 100$ price. Probably you could better describe what we get for 100$ (today 25$). If i look at the Aron Granbergs pathfing engine, then i see there already grids on a terrain, they are not visible in game mode, but they are there. Then i also know the Honey Hex framwork, which does a nice texture blending and simply provide the basics for a civilization 5 kind games. This makes this asset valuable. I belive, that i just don't see where the fucus ares are.

    Could you explain us where the emphases are? (As a developer, for what we would need a lot of time, if we would implement alone a custom grid.)

    Thanks in advance!
     
  33. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Grids primary focus is on making grid algorithms easy to write in a wide variety of contexts (different type of games, for logic and graphics).

    As a few simple examples, with Grids, it is easy
    • to have two different representations of the same data (for a game world and a mini-map, for instance).
    • to roll out your own rendering technology to support innovative styles or unusual games (it is, for example, now trivial to build custom meshes for grids based on grid data).
    • to define shapes mathematically (for example, to define patterns in 2D games or groups of units in RTS games).
    • easy to build grids in different shapes.
    • to use grids on all types of surfaces.
    It is also easy to wrap any other grid in one of our interfaces, and use our algorithms for that.

    You can write code such as:

    Code (csharp):
    1. foreach(var point in grid.Where(p=>p.DistanceFrom(effectCenter)) grid[point].ApplyEffect();
    And of course, you get a large number of grids: rect, diamond (for isometric games, for instance), hex, triangular, polar, 1D, layered 3D. You can nest grids. You can treat partial grids as complete grids. You can have cells of different sizes.

    We built grids over a period of 2 and a half years. What will take developers long is writing code for all the math (grid point arithmetic, mapping from world to grid and back, dealing with grid shapes and grid geometry) and building all the machinery that makes algorithms elegant to implement for games. Moreover, the developer probably won't have as much time to try out different methods as we have. And we have some 80 examples of how to do various things (40 odd that comes with Grids, and 40 more on our web site).

    We have built almost 90 games with grids (30 for our Unity campaign, 30 for our Game Maker campaign, and a bunch of others as examples, in jams and so on), so we have a good idea of the code you are likely to write.

    And then finally, you get support from people that probably know more about grids, grid algorithms, and related things than anyone else in the world. (The questions on this forum and on our knowledge base - still new - should give you an idea). ;-)

    But if you are not convinced, send me an email and I will send you a copy to evaluate :)
     
  34. apocriva

    apocriva

    Joined:
    Nov 3, 2011
    Posts:
    25
    I haven't worked much with Grids yet, so I suppose I'm not 100% familiar yet with how to set things up even outside of multiplayer. :) I'm using a FlatHexTileGridBuilder with a custom GridBehaviour that is doing some procedural generation stuff to create a level. I want that generation to happen on the server, and the result to be propagated out to the clients.

    I also haven't worked much with the new Unity networking yet, so I'm not even sure how to propagate data at all yet! I'll keep plugging away and I'm sure things will become clear.

    That said, it would be lovely to see a network-enabled example for Grids. :)
     
    Herman-Tulleken likes this.
  35. mkgame

    mkgame

    Joined:
    Feb 24, 2014
    Posts:
    592

    Thank you for this extensive description. I don't like and don't make smartphone games, im on an RTS game and if I want to waste my little time, then with AAA games. I guess, this grid asset is a must to have for smartphone games and this asset also have a place in the desktop oriented games, like in UFO, Planet Anh., Heroes, Age of Wonders and so on. I know a such asset exists, and if i need a grid, i know where i find it ;) I would much more impressed, if i would see an AAA style desktop grid game demo. (Probably with the grid on mesh, i didn't see any 'real' hills in grid games.) But don't do this for me, just if you see potential in it to sell more licenses.
     
    Herman-Tulleken likes this.
  36. apocriva

    apocriva

    Joined:
    Nov 3, 2011
    Posts:
    25
    I am getting these two warnings:

    Assets/Gamelogic/Plugins/Grids/Unity/EditorSupport/GridBuilders/DiamondMeshGridBuilder.cs(34,39): warning CS0414: The private field `Gamelogic.Grids.DiamondMeshGridBuilder.centerRect' is assigned but its value is never used
    Assets/Gamelogic/Plugins/Grids/Unity/EditorSupport/GridBuilders/RectMeshGridBuilder.cs(32,39): warning CS0414: The private field `Gamelogic.Grids.RectMeshGridBuilder.centerRect' is assigned but its value is never used

    Grids otherwise has very strong production value, so these warnings kind of stick out like sore thumbs. :) (Unless I've done something strange to mangle it! lol)
     
    Herman-Tulleken likes this.
  37. murteas

    murteas

    Joined:
    Feb 14, 2012
    Posts:
    62
    Ah... man! I've been watching this library for a long time and I missed the sale just this week. :( I can't believe it.
     
  38. wightwhale

    wightwhale

    Joined:
    Jul 28, 2011
    Posts:
    397
    I'm getting the trial warning even though I bought the full version, what file do I need to redownload to fix the issue?
     
    Herman-Tulleken likes this.
  39. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    Hi all,

    I just bought Grid Pro, and I'm trying to port my iOS native game (Numbers Addict) to Unity using this asset.

    I just don't understand how to create an "empty" grid, and when I click on a column, a new element drop to first empty "square" of my grid.

    I think I have to use "GridBehaviour<RectPoint>" with "MatchCells".

    But I just don't understand how to do what I just explained.

    I already check the exemple "match grid", but the grid is always full.

    Thank a lot.

    Best regards,

    AB.
     
  40. Ixox

    Ixox

    Joined:
    Mar 15, 2015
    Posts:
    1
    Hi,

    I just bought Grid Pro that i'm trying to use with Unity 5.0.3p2.
    I don't get consistent behavior with the mouse clicking on the cells.

    I followed the youtube video (How to set up a grid in the editor (Using Grids)) and I cannot have the highlighting on mouse click working on a simple Hex grid (yes "colors" and "is interactive" are checked).

    Then I tried the scene from "02-Grid pro" folders and i got weird results :
    . All "Grids with code" examples work fine.
    . "Grids with editor" does not work fine.
    In BasicGridSetup, only the PolarRectGrid works, the 2 other don't change when i click on them.
    LightOutTri does not use correclty the mouse position. As if there were a scale different from 1 on mouse.x an mouse.y.
    LightOutCairo works fine, Pipes works fine.

    In "02-Grid Basic", LightsOutHEx throw an exception in the console:
    NullReferenceException: Object reference not set to an instance of an object
    Gamelogic.Grids.GridBuilder`1[Gamelogic.Grids.PointyHexPoint].get_MousePosition () (at Assets/Gamelogic/Plugins/Grids/Unity/EditorSupport/GridBuilders/GridBuilder.cs:38)
    Gamelogic.Grids.GridBuilder`1[Gamelogic.Grids.PointyHexPoint].ProcessInput () (at Assets/Gamelogic/Plugins/Grids/Unity/EditorSupport/GridBuilders/GridBuilder.cs:57)
    Gamelogic.Grids.GridBuilder`1[Gamelogic.Grids.PointyHexPoint].Update () (at Assets/Gamelogic/Plugins/Grids/Unity/EditorSupport/GridBuilders/GridBuilder.cs:48)

    FlatBrickTest and PointyBrickTest does not change the color where I click. It changes the color but there is a shift on the X position.

    My question is: is unity 5.0.3 officially supported ?
    Do i have to do something special to have it working ?

    Thanks,

    Xavier
     
    Last edited: Jun 28, 2015
    Herman-Tulleken likes this.
  41. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Thanks for the feedback; we will keep this in mind if we make some more examples!
     
  42. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Can you please send us an email at support@gamelogic.co.za so that we can help you with this? Thanks!
     
  43. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hmmm yes you cannot create an empty grid in the editor. You can, however, do it in code (by simply not instantiating cells). If you incorporate the code for creating a grid (in the 00 Start Here folder) into the match game, you should get what you need. You will need to change the match from a grid behaviour to a normal mono behaviour, and then use the grid and map you created in code instead of the properties Grid and Map.

    Does this make sense?
     
  44. murteas

    murteas

    Joined:
    Feb 14, 2012
    Posts:
    62
    If I buy grids lite, can I upgrade to basic or pro later with a discount, or still the full price?
     
  45. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    You can upgrade for the difference. (The Asset store now handles upgrades smoothly), so from Lite to basic, you will pay $30 at the moment, for example.
     
  46. murteas

    murteas

    Joined:
    Feb 14, 2012
    Posts:
    62
    Awesome. Thanks!
     
  47. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    In Fact I use your match template and change a little bit the cell class. By default the number is -1. If it's -1, it doesn't appear on the screen.

    What do you think ?

    Thanks !


    And another question if I can ;)

    It seems I can't add a sprite and apply to him a different scale to adjust him (compared to his parent, the cell).

    It doesn't work.

    Do you know why ? Could you help me please ?

    Thanks !
     
  48. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Well if it works then it is fine :) (But do make sure you are not getting any errors.)
    It should work, and I tested this on my side. Are you adjusting the size by setting the transform? I know Sprites are sometimes a bit finicky...
     
    ababab5 likes this.
  49. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    ahah, it's the good world!

    Again a question, sorry for that and thanks again for all your quick replies :

    Is there a way to add a background to a grid ? I mean each "cell" can have his background, and independent of the cell ..

    Thanks !
     
  50. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    ababab5 likes this.