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. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Finally back at Grids again. :)

    I tried to implement a simple 3D grid today but I am not sure this is the most efficient way to do it. It works, so maybe I shouldn't worry too much about it, but still... ;)

    Code (csharp):
    1.  
    2. using Gamelogic.Grids;
    3. using UnityEngine;
    4.  
    5.  
    6. public class LevelBuilder : GLMonoBehaviour
    7. {
    8.     public Tile tilePrefab;
    9.     public GameObject tileRoot;
    10.     public Texture2D heightMap;
    11.    
    12.     private RectGrid<Tile> grid;
    13.     private IMap3D<RectPoint> map;
    14.  
    15.     private int[] colours = new int[8] { 1, 2, 3, 4, 1, 2, 3, 4 };
    16.  
    17.  
    18.     public void Start()
    19.     {
    20.         BuildGrid();
    21.     }
    22.  
    23.  
    24.     public void Update()
    25.     {
    26.         if(Input.GetMouseButtonDown (0))
    27.         {
    28.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    29.             RaycastHit hit;
    30.  
    31.             if (Physics.Raycast(ray, out hit))
    32.             {
    33.                 if (hit.collider != null)
    34.                 {
    35.                     RectPoint rectPoint = map[hit.collider.transform.localPosition];
    36.  
    37.                     if (grid.Contains(rectPoint))
    38.                     {
    39.                         // toggle original point
    40.                         grid[rectPoint].Switch();
    41.  
    42.                         // toggle its neighbors
    43.                         foreach (RectPoint neighborPoint in grid.GetNeighbors(rectPoint))
    44.                         {
    45.                             grid[neighborPoint].Switch();
    46.                         }
    47.                     }
    48.                 }
    49.             }
    50.         }
    51.     }
    52.  
    53.  
    54.     private void BuildGrid()
    55.     {
    56.         Vector3 center = new Vector3(0, 0, 0);
    57.         int count = 0;
    58.        
    59.         grid = RectGrid<Tile>.Rectangle(8, 8);
    60.        
    61.         map = new RectMap(new Vector2(2, 2) * 1.5f)
    62.             .To3DXZ();
    63.        
    64.         foreach(var point in grid)
    65.         {
    66.             var tile = Instantiate(tilePrefab);
    67.  
    68.             tile.transform.localPosition = map[point];
    69.             tile.transform.parent = tileRoot.transform;
    70.  
    71.             tile.SetColor(ExampleUtils.colors[colours[point.X]]);
    72.  
    73.             grid[point] = tile;
    74.  
    75.         }
    76.     }
    77. }
    78.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using Gamelogic.Grids;
    4.  
    5. public class Tile : GLMonoBehaviour
    6. {
    7.     private bool activated;
    8.     private Color myOriginalColor;
    9.  
    10.     public void Awake()
    11.     {
    12.         activated = false;
    13.     }
    14.  
    15.     public void SetColor(Color color)
    16.     {
    17.         renderer.material.color = color;
    18.         myOriginalColor = color;
    19.     }
    20.  
    21.     public void Switch()
    22.     {
    23.         renderer.material.color = activated ? myOriginalColor : Color.white;
    24.         activated = !activated;
    25.     }
    26. }
    27.  
     

    Attached Files:

  2. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Normally, I would not worry about efficiency unless you have a clear problem. Nothing in your code shouts out at me as being inefficient (you could potentially replace the raycast with a direct calculation, but I should not think it's much faster, if at all). I think it's good :)
     
  3. Tinjaw

    Tinjaw

    Joined:
    Jan 9, 2014
    Posts:
    518
    I am attempting to run the example. When I load it I get a warning: "The class defined in script file named 'LightsOutHex' does not match the file name!". Also, when I run it it goes straight to the end and won't restart.

    http://screencast.com/t/0mOWi6ZKC
     

    Attached Files:

  4. Jonathan-Bailey

    Jonathan-Bailey

    Joined:
    Aug 12, 2013
    Posts:
    79
    Hi Tinjaw

    There was a problem when we exported the package, but we’ve uploaded a new one, so please try again :)
     
  5. NandusMasta

    NandusMasta

    Joined:
    Apr 9, 2011
    Posts:
    63
    Great package! I've been using it for a few days and it has practically everything you could ever want for handling grids. One thing though, how would one go about generating a random point in the grid, which is a certain distance away(min/max range) from previous generated points? Any pointer on this would be greatly appreciated.
     
  6. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    NandusMasta,

    One way would be to do something like this:

    Code (csharp):
    1.  
    2. var point = grid.Where(p => InRange(p, q, minDistance, maxDistance)).SampleRandom(1).First();
    3. //SampleRandom is a useful method defined as an extension method in the examples
    4.  
    And InRange can be defined as:

    Code (csharp):
    1.  
    2. public bool InRange(PointyHexPoint point1, PointyHexPoint point2, int minDistance, int maxDistance)
    3. {
    4.    var distance = point1.DistanceFrom(point2);
    5.  
    6.    return distance >= minDistance  distance <= maxDistance;
    7. }
    8.  
    This of course gives the grid distance. If you want Euclidean distance instead, you can use the map:

    Code (csharp):
    1.  
    2. public bool InRange(PointyHexPoint point1, PointyHexPoint point2, float minDistance, float maxDistance)
    3. {
    4.    var distance = (map[point1] - map[point2]).magnitude;
    5.  
    6.    return distance >= minDistance  distance <= maxDistance;
    7. }
    8.  
     
    Last edited: Mar 8, 2014
  7. NandusMasta

    NandusMasta

    Joined:
    Apr 9, 2011
    Posts:
    63
    I've tried your code and I am getting an error related to the Where method, which seems to be missing in the PointyHexGrid class. I searched the API and the closest thing I could find was the WhereCell function, from what I read up it would not be suitable for solving this problem though.
     
  8. Herman-Tulleken

    Herman-Tulleken

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

    The Where method is an extension method provided in System.Linq. You will need to add "using System.Linq" with the other using statements at the top of the file to be able to use it.
     
  9. NandusMasta

    NandusMasta

    Joined:
    Apr 9, 2011
    Posts:
    63
    Thanks Herman for your help. I was able to crack what I wanted using your code as reference. Basically I created 2 functions, one to filter out points already taken and avoid getting repeated points. And then another to make sure every new point was not very close to all previously taken, nor very far from at least one of them.

    I dabbled into LINQ in my first job, back in 2003, but since then I never touch the thing; that's why I was a little lost. In any case I think am going to change some of my old school vectors for LINQ capable collections, since I think that in spite of any performance loss, the where statements give you great flexibility and ease for queries in your collections.
     
  10. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Is there an easy way to count neighboring points which match a certain criteria? Something like...

    Code (csharp):
    1.  
    2. if (grid.GetNeighbors(point).Where( @magic!  ).Count() >= 2)
    3.  
    I don't see a handle by which I could check the points the GetNeighbors() function is iterating.
     
  11. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    You can add a predicate in Count, for example, suppose the criteria is to only count red neighbors

    Code (csharp):
    1.  
    2. int redNeighborsCount = grid.GetNeighbors(point).Count(p => IsRed(grid[p]));
    3.  
    4. if(redNeighborsCount >= 2)....
    5.  
     
  12. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Nice. Some notations of Linq are still a book with seven seals to me. :)

    Hopefully gonna be able to show my redesigned prototype this week.
     
  13. Deozaan

    Deozaan

    Joined:
    Oct 27, 2010
    Posts:
    707
    I bought the Grids asset pack a while ago and am just now getting into it for the first time. I have to say I'm really disappointed in the included documentation.

    A single page PDF file with broken "links" (really just underlined text) to online resources? At least include the API reference or something.

    EDIT:

    The quick-start tutorial says to use the following line of code:

    Code (csharp):
    1. cell.transform.SetXY(map[point]);
    But there doesn't seem to be any SetXY() function defined anywhere in the entire project. This is really disappointing.
     
    Last edited: Mar 26, 2014
  14. Tinjaw

    Tinjaw

    Joined:
    Jan 9, 2014
    Posts:
    518
    Today I downloaded the Daikon Forge Lights Out unitypackage and I am still getting the error "The class defined in script file named 'LightsOutHex' does not match the file name!"
     
  15. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Did you import the namespace of Grids? Try putting this line

    Code (csharp):
    1. using Gamelogic.Grids;
    at the top of your script.
     
  16. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    How's unit testing going.

    Any news on more Joyful IOS coding with Grids ?
     
  17. Deozaan

    Deozaan

    Joined:
    Oct 27, 2010
    Posts:
    707
    That's a relatively easy fix. Just rename the class to match the filename, or else rename the filename to match the class. But of course it's useful to inform the developer of the issue so he can fix it for everyone, which is what I think you are probably doing here.


    The quick-start tutorial doesn't mention that that is necessary, but yes, I did do that because otherwise the first two steps in the tutorial wouldn't work either.

    I even tried adding this:

    Code (csharp):
    1. using System.Linq;
    In case the SetXY() function required that, but I'm still getting the error:

     
  18. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    @Deozaan

    The tutorial is out of date. We have added a lot of functionality recently, and have not kept everything up to date. Sorry about that. I updated the quick start tutorial with the correct code and added some notes to avoid confusion. We will go over the other tutorials too and make sure that all is up to date.

    http://gamelogic.co.za/grids/documentation-contents/quick-start-tutorial/

    The PDF will be fixed in the next update, which should be next week.In the mean time, here are all the links:

    Tutorial, FAQ and Knowledge Base
    http://gamelogic.co.za/grids/documentation-contents/

    Grid Index
    http://gamelogic.co.za/grids/documentation-contents/quick-start-tutorial/grid-index/

    API Documentation
    http://www.gamelogic.co.za/documentation/grids/

    What is new in Grids 1.7
    http://gamelogic.co.za/grids/what-is-new/

    @TinJaw

    A stupid mistake on our part; I updated the package.
    http://gamelogic.co.za/grids/example-games/lights-out-with-daikon-forge/

    @rocki

    We are finalising the last things for Grids 1.8. It should be ready next week.
     
    Last edited: Mar 29, 2014
  19. Tinjaw

    Tinjaw

    Joined:
    Jan 9, 2014
    Posts:
    518
    There is still an issue.

    FYI, I am able to make the necessary changes to get it working, but I am letting you know so new users don't have issues with the package.
     
  20. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    @Tinjaw Thanks, I appreciate it. It is very strange; I tested everything when I uploaded it, but I when I tested it again just now I see the script is was still wrong. Perhaps I was too tired when I uploaded the fix! It should be fixed now for everyone else.
     
  21. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    Hi,

    I am having trouble using Grids with DF GUI.
    Help please?

    Used this example : http://gamelogic.co.za/grids/example-games/lights-out-with-daikon-forge/

    However, I am getting the following error.

    Assets/LightsOut/Scripts/PanelEvents.cs(13,17): error CS0246: The type or namespace name `DFLightsOutHex' could not be found. Are you missing a using directive or an assembly reference?

    Is a script missing?
     
  22. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    @Trithilon

    Amazingly, there was still an error with the package (I think it must be cursed). I fixed it and tested it on my side. Could you please download it again and give it a try? Let me know if there is still an error.
     
  23. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    Hi, I just checked the package. The old error is gone but I got this warning.

    The class defined in script file named 'LightsOutHex' does not match the file name!

    However it was an easy fix changing the filename to the class name (I guess it got over-written).


    So, the example works - but not as expected. Whenever I click a HexCell - it Toggles the Hex which is -1 on the X axis (the left hex of the one you clicked).

    Here is a webplayer build to show you the problem :
    https://dl.dropboxusercontent.com/u/9030688/DFGridsTest/DFGridsTest.html

    Thanks for helping out with this. :)
     
  24. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Another suggestion and a question :)

    - Wouldn't it make sense to include .North/.South/etc... for RectGrids as well? I can easily look up the cell above in a HexGrid but with RectGrids it appears that I have to manually add and subtract coordinates.

    - In a RectGrid, is there an easy way to look up all cells in the same row/columns which are connected to a specified cell? Imagine a playing grid like in your Game 22 example, but selection would end at the most inner cell and not include those on the opposite.
     
  25. Deozaan

    Deozaan

    Joined:
    Oct 27, 2010
    Posts:
    707
    I don't understand the API documentation for the AStar functions, and as best as I can tell there are no included demos of A* (I would expect the Algorithms folder to contain a demo of the A* algorithm), none of your thirty 1-day games used A*, and none of the extra demos and examples use A*.

    The API documentation seems to be somewhat incomplete on the matter (for example, it explains what "heuristicCostEstimate" is but not what "isAccessible" is or how to get that value).

    It uses too many terms I'm not familiar with to know how to use it. What is a TCell? or a TPoint? How do I pass in an IGrid<TCell,TPoint>? What's the difference between "heuristicCostEstimate" and "cost" and why would I ever want to use an estimate instead of the actual cost?

    How do I pass in the necessary functions required by the AStar function to calculate the heuristicCostEstimate, isAccessible, and cost values?

    This is so frustrating because I can tell that Grids is a very powerful and potentially useful system, but I've been poking at it for about a week now and I've barely managed to get a simple rectangular grid working. The API reference is obtuse. The example scenes show off complex stuff without explaining the basics first, and in the end there's not even a tutorial on how to set up a regular rectangular grid. (The "00 StartHere" RectTest scene uses checkers-like grid.)

    In my opinion the documentation is very, very poor. Yes, it tells me how to make a specific thing, but it fails at actually teaching me the concepts and methodology required to do it on my own.

    I'm so disappointed in Grids. :( At this point I feel like I could have written my own (admittedly not as robust or widely usable) grid system that specifically fit my own needs a lot faster than the progress I've made with Grids.
     
  26. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    I agree on one point - the documentation could be practical. I am guessing a couple of video tutorials on teaching the basics will go a LONG way to helping people work with your grid. Maybe a demo of making a simple match-3 game on a video might do the trick. :)
     
  27. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    @Trithilon

    It's super weird that the filename issue persists; I will do a proper check again tomorrow.

    The offset is caused by the resolution size. Make sure your player settings is the same resolution (if you change the web res to 1024x768 it works fine; alternatively you can change the target resolution on the DF GUI Manager - as long as they are the same).

    And yes, up to now, because everything happens in code, we thought video tutorials may not do the trick. But now that grids can be made in the editor, we definitely want to make some.

    @c-Row

    You can already say RectPoint.North and so on (remember it's on the point, not the grid).

    http://www.gamelogic.co.za/documentation/grids/struct_gamelogic_1_1_grids_1_1_rect_point.html

    In Algorithms, there is a function GetConnectedRays, which is what I think you mean. That gives a list of rays from the query point that are connected in each direction.

    (GetConnectedLines is similar, but it gives the full line that contains the point in the row/column).

    Let me know if this is indeed it.

    @Deozaan

    I am sorry our documentation is unclear. We take many things for granted and make many assumptions about how users will learn our package, and clearly get many things wrong. Your feedback is very valuable in helping us fix these issues, and we definitely want to fix them.

    We are beginning to recognize some of the more systematic mistakes we made - showing off fanciness in our examples, instead of being clear; not having enough comments in the examples; adding features faster than documentation such as the API docs and tutorials.

    The fact that Grids is implemented in a very generic and abstract way does not help matters. We are finishing up Grids 1.8, and then we will concentrate on making features accesible, filling holes in the tutorials, and making some more useful tutorials as well.

    ---

    The maze generation example uses AStar if you want to look at that. The cost is normally the distance between cells; the heuristic cost is an overestimate that the algorithm can use to eliminate bad paths quickly. You can give the cost if it's something other than distance. We will definitely update our documentation. The isAccesible parameter is a delegate that takes a cell and returns whether that cell can be reached or not. TPoint is the point type of the grid(such as RectPoint), and TCell is the type of the thing you have in your grid (such as Cell in many of the examples). IGrid<TPoint, TCell> is an interface implemented by all grids. For example, a RectGrid<MyCoolCell> implements IGrid<RectPoint, MyCoolCell>, so the AStar function

    Code (csharp):
    1.  
    2. static IEnumerable<TPoint> Gamelogic.Grids.Algorithms.AStar< TCell, TPoint >(IGrid< TCell, TPoint > grid,TPoint start,TPoint goal )
    3.  
    Can by called on a rect grid like this:

    Code (csharp):
    1.  
    2. RectGrid<MyCoolCell> grid;
    3. Rectpoint start = new RectPoint(0, 0);
    4. RectPoint goal = new RectPoint(5, 4);
    5.  
    6. var path = AStar(grid, start, goal);
    7.  
    Normally, C# can figure out the type parameters, but you can specify them too:

    Code (csharp):
    1.  
    2. IEnumerable<RectPoint> path = AStar<RectPoint, MyCoolCell>(grid, start, goal);
    3.  
    ----

    I hope this makes things a bit clearer. If you want I can give you a more detailed example.
     
  28. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Well... uhm... crap. :D To add insult to injury I even used it in my code. Ahem.


    This sounds indeed like what I am looking for. I will try to implement it and see what happens. I suppose I can use the IsNeighborsConnected parameter to limit this to horizontal or vertical rays only by something like this?

    Code (csharp):
    1.  
    2. private bool IsOnVertialAxis(RectPoint point1, RectPoint point2)
    3. {
    4. return point1.X == point2.X;
    5. }
    6.  
     
    Last edited: Apr 8, 2014
  29. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Hehe, even I sometimes forget some features on occasion :) !

    Yup, that should do the trick.
     
  30. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    It appears that GetConnectedRays does exactly what I was looking for. Changed my game from only supporting square maps to working with shapes of various forms. :)



    Please don't mind the blatantly stolen but temporary backdrop. :D
     
  31. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Glad it worked :) (It's looking rather nice; you should put up a playable!)
     
  32. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Once I am completely happy with it I will create a WIP thread including links to its previous versions to document the design changes. :)
     
  33. Psygantic

    Psygantic

    Joined:
    Mar 4, 2014
    Posts:
    10
    I would appreciate more attention paid to getting Grids working properly with DFGUI.

    As of today, the LightsOut example at http://gamelogic.co.za/grids/example-games/lights-out-with-daikon-forge/ straight-up does not work and seems like it hasn't been tested with the current versions of Grids and DFGUI. Starting with a fresh project, I imported the example package, Grids 1.7, and DFGUI 1.0.15. Changed the class name LightsOutHex to DFLightsOutHex.

    Next problem: Type `DFLightsOutHex' does not contain a definition for `OnClick'. OK, so it seems like there are two methods of detecting mouse clicks, and this one might be legacy. I just commented out the call to OnClick in PanelEvents.cs line 25 to get things compiling.

    Next problem: Can't hook up the reference to DFLightsOutHex.cellPrefab because the types don't match (it's expecting Cell instead of DFCell). Easy enough to fix: changed all instances of class Cell in DFLightsOutHex.cs to DFCell.

    Next problem: Type DFCell does not contain definitions for SetColor or HighlightOn. This is starting to look like completely mismatched code now. So I went through and updated DFLightsOutHex.cs to use DFCell's methods (On instead of HighlightOn, SetColors once instead of SetColor every state change.) Now everything compiles and I can attach the DFCell prefab reference to the DFLightsOutHex object in the example scene.

    Next problem: When I run the scene, all the hexes are stacked in the same position at the upper-left corner of the screen.

    So now I'm out of ideas. Could you try it with the current versions of those packages? My suspicion is that the current example package contains outdated code because otherwise I can't see why Trithilon got it semi-working a week ago but it won't work for me now.

    Also, from Trithilon's posted example, it seems that there may be more needed to get Grids + DFGUI working correctly. In my own experiments a couple months ago, I was able to get a hex grid to render under DFGUI but the coordinate mapping was screwed up in much the same way as in Trithilon's example.
     
  34. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    @Anomalous

    The experience you are describing is definitely not the one you should have.

    I have tested the package, but somehow it is still wrong (I managed to duplicate your experience). The only explanation I can offer is that somehow the package ended up in a weird state.

    I tried to rebuild the package, but it keeps the wrong script file. After a while, I rebuild the example from scratch, and tried to export that. Now all the scripts are there, but I cannot open the scene.

    It is very strange. I will experiment some more and make the update as soon as I found the problem.
     
  35. Caruanas

    Caruanas

    Joined:
    Apr 15, 2014
    Posts:
    7
    Hi Herman!

    I am a new Grids user, and so far my experience with its functionality has been excellent. It really makes things easier to handle!

    However I am having some issues with figuring out what exactly it can or cannot do due to limited documentation. Specifically, I am trying to figure out whether it provides a way of getting the grid point from a cell. Let me try to explain a bit better:

    The grid returns the cell at a given point, for example

    Code (csharp):
    1.  
    2. RectPoint point = new RectPoint(0, 0);
    3. MyObject o = grid[point];
    4.  
    Is there an inbuilt way to do the opposite of that, i.e. providing the grid with the object o, and it return its point 0, 0?

    Thanks in advance!
     
  36. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    I think we solved the isssues now. (The scene opened fine after I restarted Unity, so it seems to have nothing to do with the package per se). I have also tested the process from the package downloaded from the link.

    (Note, I have imported the packages in this order: Daikon Forge, Grids, LightsOut_DaikonForge).

    The example cells do not provide this functionality. (The idea with grids is that you will implement your own cells; we just provide some cells as examples).

    It is my opinion that having cells know their grid locations is bad design; similar to the way it is bad design for array elements to know their array indices. However, I admit in certain cases it can be convenient, and it's not difficult to make it so. To make sure everything is always in synch, I would define my own function to assign cells to grid positions. The cell will have a property GridPoint, like this

    Code (csharp):
    1.  
    2. public class SmartCell : Cell
    3. {
    4.     public RectPoint GridPosition {get; set;}
    5. }
    6.  
    7. //You can then replace the Cell script with this script on the prefab.
    8.  
    Then in your code, define a function for assigning cells to the grid:

    Code (csharp):
    1.  
    2. public SetCell(RectGrid<SmartCell> grid, SmartCell cell, RectPoint point)
    3. {
    4.    grid[point] = cell;
    5.    cell.GridPoint = point;
    6. }
    A bit more work, if you want to make things more robust: wrap this functionality in your own grid (Implement the interface IGrid<SmartCell, RectPoint>) and override the index access operator to do this. All other functions can simply delegate to the internal grid. Something like this:

    Code (csharp):
    1.  
    2. public class SmarGrid : IGrid<SmartCell, RectPoint>
    3. {
    4.     private RectGrid<SmarCell> rectGrid;
    5.  
    6.     public SmartCell this[RectPoint point]
    7.     {
    8.         get
    9.         {
    10.              return rectGrid[point];
    11.         }
    12.  
    13.         set
    14.         {
    15.               rectGrid[point] = value;
    16.               value.GridPoint = point;
    17.         }
    18.     }
    19.  
    20.     public IEnumerable<RectPoint> GetNeighbors(RectPoint point)
    21.     {
    22.         return rectGrid.GetNeighbors(point);
    23.     }
    24.  
    25.     // and so on
    26. }
    27.  
    If you implement this interface, all grid functions will work with it, except that it won't support shape building directly. Depending on your needs, you can simply construct the internal grid with the right shape in the constructor, or you could provide your own factory methods. (You could also implement the fluent interface functionality for this grid, but this is quite technical and hard. I would only do it if you really want to code grids in lots of shapes.)

    Let me know if this makes sense, or you have any more questions!
     
    Last edited: Apr 16, 2014
  37. Psygantic

    Psygantic

    Joined:
    Mar 4, 2014
    Posts:
    10
    Thank you - this is working better now.

    I did encounter a problem with coordinate mapping when the grid's container panel is moved anywhere but top-left of the UI. A simple repro:

    - In a new project, import DFGUI, Grids, LightsOut_DaikonForge. Open the LightsOut scene.
    - In the dfPanel properties (not the transform) of the root Panel object, make the Layout look like: {Left: 256, Top: 0, Width: 768, Height: 768}. In other words, make it a square shifted 256 pixels to the right side of the viewport.
    - Run the scene and click on some hexes. The hexes that respond are 256 pixels to the right of where you actually clicked.

    A workaround for this problem is to create another dfPanel and put the root panel inside it at 0,0. The new parent panel can then be moved around as desired, and clicks to the root panel are mapped correctly to hexes as far as I can tell. This seems like a hack though.
     
    Last edited: Apr 16, 2014
  38. peterpunk

    peterpunk

    Joined:
    Nov 25, 2012
    Posts:
    11
    Hi,

    1. could you post a (as simple as possible) example on how to use Unity's 4.3 native sprites as prefabs for cells (no NGUI)?

    2. And on how to put other sprites inside those cells?

    Thanks.
     
  39. peterpunk

    peterpunk

    Joined:
    Nov 25, 2012
    Posts:
    11
    Actually did it myself, its not a problem at all ;)
     
  40. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    Thanks for the headsup on this issue, and the workaround. DaikonForge does not provide a way to find the mouse position relative to a panel (it's always in global screen coordinates), so we had to make one that was reworked from their internal functions. IDF's coordinate code is very complicated, and I do not understand it fully, (as the bug you mention demonstrates). I had a look at it again, and I could not figure out how to reliably detect relative coordinates in a consistent way. (I asked on their forum too, but it seems that it is really non-trivial). We will look into it some more; I will let you know how it goes.

    Cool, glad you managed! Once you understand the basics, it's not difficult at all.
     
  41. Steamroller

    Steamroller

    Joined:
    Jan 2, 2013
    Posts:
    71
    Just bought your package and now digging into it.

    I have a few questions:
    • We want to provide an in-editor tool for our artists to create hex levels. I know you have a prototype for a custom editor, but does that require changes to your library to work, or can i write something similar with the current release of Grids?
    • Is there a way to serialize the grids and maps in a prefab, scene or an external file format? or is Grids only meant to be an in-memory runtime data structure?
    • Can the grid be easily resized without clearing the grid? or do we need to plan ahead and create a much bigger grid than we plan to use?
    I'm sure ill have more questions as I keep digging.

    Thanks in advance.
     
  42. Herman-Tulleken

    Herman-Tulleken

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

    1.

    You can use the current version of Grids; we have not modified the core library for editor support.

    2.

    You cannot serialize grids directly (the main reason is that grids uses custom delagates to control their shape).

    However, it is relatively easy to get your data serialized. There are two options.

    If your grids (for different levels) have the same shape, you can simply seriliaze the values as an array, using this:

    Code (csharp):
    1.  
    2. var gridContents = grid.Values.ToArray();
    3.  
    When you deserialized this, you simply read the values back into the grid:

    Code (csharp):
    1.  
    2. int i = 0;
    3.  
    4. foreach(var point in grid)
    5. {
    6.    grid[point] = gridContents[i];
    7.    i++;
    8. }
    9.  
    If you have different shapes for each level, you will need to also save shape information. The most straightforward approach is to use a fixed shape, and an additional boolean grid that says whether a cell of the fixed-shaped grid is in the level or not. You will also need to save the dimensions of your fixed shape. A rectangle shape is probably the best (in which case you will need to save the width and height).

    You may put your save information in a class like this:

    Code (csharp):
    1.  
    2. [Serializable]
    3. public class GridData
    4. {
    5.    public int width;
    6.    public int height;
    7.    public MyCellData[] gridContents; //MyCellData contains all the data you need to reconstruct your particular cell
    8.    public bool[] isCellInLevel;
    9. }
    10.  
    You then use isCellInLevel to filter grids. (You can wrap everything in a single class that implements the IGrid interface, or you can make a design using the raw constructors - the last approach is a bit complicated; the raw constructors are parallelograms or rectangles by default, and takes a containment function. I quickly tried to work something out, but it requires a bit of thinking to do it right.)

    Remember to separate your cell data from the actual unity objects that represent a cell. (Since Unity objects also cannot be serialized directly). Typically, you will have a class with only data, (MyCellData), and a cell for the visual representation (MyCell).

    Also, it seems to me unlikely that you would need to serialize maps (most maps do not depend on the grid in the sense that maps are infinite - they map points to where they would be in an infinite sized-grid). (We are introducing a few maps in the next version for which this is not the case, but even there the maps are easily re-created from the grid data). But maybe you have a use-case that I am missing; let me know if that is the case.

    3.
    You will always have to create a new grid, and this is quite fast. What is not fast, is destroying and recreating cells. However, you could easily minimize this:

    Code (csharp):
    1.  
    2. public PointyHexGrid<MyCell> Resize(PointyHexGrid<MyCell> oldGrid, int newSize) //lets use a hexagon shape
    3. {
    4.    var newGrid = PointyHexGrid<MyCell>.Hexagon(newSize);
    5.  
    6.    foreach(var point in newGrid)
    7.    {
    8.       if(point in oldGrid)
    9.       {
    10.          newGrid[point] = oldGrid[point];
    11.       }
    12.       else
    13.       {
    14.           newGrid[point] = ... //make a new cell
    15.       }
    16.    }
    17.  
    18.    foreach(var point in oldGrid.Where(p => !newGrid.Contains(p))
    19.    {
    20.       Destroy(oldGrid[point].gameObject); //or something similar.
    21.    }
    22. }
    23.  
    You could also pool cells for additional speed.

    ---

    I hope the above is clear and helpful. Please let me know if I can clear anything up or you have more questions.
     
    Last edited: Apr 25, 2014
  43. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Any chance for an ETA on smoother IOS integration and 1.8 release.

    Cheers.
     
  44. Mi_Gr

    Mi_Gr

    Joined:
    Dec 5, 2013
    Posts:
    17
    Yes, is the new version just foreseeable? Maybe with some more examples from your 30 days Game Pack? Would be great! :)
    Thanks in advance.
     
  45. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    We are working very hard to get it finished! We should submit next week (I hope!).

    The bulk of the code has been written, but as we update our (many many!) examples, we discover quite a few small issues. We want our "editor grids" (as we call them) to be as flexible and powerful as the "programmatic grids". For otherwise the ability to have grids built in the editor would just be a fad; you would actually still have to use programmatic grids for anything vaguely interesting.

    But getting to this flexibility turned out to be quite a challenge.

    Here are some of the issues we had to deal with so far to give you an idea what I'm talking about:

    Programmatic grids can be constructed using the static shape functions (such as Rectangle, Hexagon, Parallelogram), or using the Shape Builder methods:

    Code (csharp):
    1.  
    2. var grid = PointyHexGrid<Cell>
    3.   .BeginShape()
    4.     .Hexagon(3)
    5.     .Difference()
    6.     .Hexagon(2)
    7.   .EndShape();
    8.  
    Now the editor grids allow you to select the shape from a drop-down menu - this corresponds to the static functions. But what if you wanted to make a custom shape?

    So we had to introduce a mechanism with which it can be done.(Later, we would like to add the shape builder tech in the editor too. But that is a lot of work for a feature that I don't think many people use. For now, we just added a mechanism that allows you to code custom shapes.)

    A lot of Grids' power comes from the separation of the grid from the mapping to world coordinates - this allows all the funky grids we have made (such as the grids on spheres, torusses, and spirals). So the ability for users to create their own maps is important - so we also had to add a mechanism for specifying your own map. (This is particularly important for some of the new grids we have added to version 1.8, such as a PointList grid, which is a grid made from a list of points.)

    Another issue is how to handle mouse input on cells. The old way was simple - you just added a bit of code in the update method of your script where you had the grid. But that is (in our opinion) a clumsy way to do it for editor grids. In fact, we handle it very neatly in one place, and send a message to cells or another script that has the appropriate method. But then we need to do it for all mouse events, and we also need to handle the case where grids are not rendered with an orthographic camera...

    One thing that makes editor grids so powerful is you can immediately see what is going on. But then, we'd ideally like the user's initialization code to be executed in the editor too. So we also had to provide a mechanism to make it possible.

    And every time we discover an issue, we have to update all our examples to make sure they are "idiomatic" and use the functionality as we designed it to be used.

    ----

    There are lots of things we have to think about for the future too. One example: an important use-case for editor grids is to be able to edit cells and so build levels. This is surprisingly complex. We know, because we have actually done it for three simple - but very different - games. The ideal design was very different for the three cases, and it's not clear what the general solution should look like, or whether there should even be a general solution at all. We don't want to tell our users how to organize their cell data and presentation if we can avoid it, but it may be the only way. For now we decided not to tackle the problem, but keep things as "open" as possible to allow us to implement it in the future.

    ----

    So it's going a bit slower than expected, but I hope it will be worth it!
     
    Last edited: Apr 26, 2014
  46. Mi_Gr

    Mi_Gr

    Joined:
    Dec 5, 2013
    Posts:
    17
    Hello Herrman,

    many thanks for your reply! I'm very exited! :)
    I think it IS worth to wait!
     
  47. Herman-Tulleken

    Herman-Tulleken

    Joined:
    Nov 20, 2009
    Posts:
    358
    We just submitted Grids 1.8!

    $grids1_8.png

    This is a massive update, and I must admit I am a bit scared of what it will bring. Just tonight (it's almost midnight where I am writing from) I discovered several scenes did not even have cameras in them! (It's because it's so much fun playing with some examples in the editor that I forget to actually run them too!) In the coming week we will write some on our web site about the new editor tools, what Grids now is and is not, and what we now see the future of our package to be. We will also write some about iOS and the beloved AOT compiler, and how it keeps outsmarting us :/

    If you are a Grids user, keep an eye on our web site and keep an eye on the coming update (twitter is the most useful way to get notified of new stuff http://www.twitter.com/gamelogicza ).
     
  48. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    Excellent! Can't wait :D
     
  49. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Congrats on the new Release.
    Sounds like you guys had to go through quite a journey for 1.8 to happen.
    Another big step forward for Team Grids.

    Cheers.
     
  50. Mi_Gr

    Mi_Gr

    Joined:
    Dec 5, 2013
    Posts:
    17
    ... for the first view: great update!! And the best I've seen in the new package, the editor adjustments for blocks in 3D ... wow, very usefull!
    Now, I have to test on iOS, I hope it is then still amazing!! ;-)

    You're right, Herman, it was worth to wait! Thanks for the update! Please keep it on!

    cu