Grid Framework version 1.1.10 released

The 1.1.10 update brings in a new function, ScaleVector3(Vector scl) : Vector3 which takes in a vector and then scales it so it fits inside the grid. This is similar to AlignVector3, which was introduced in the last update, to allow performing the aligning and scaling without having to provide an actual Transform.

In other news, the hex grids are almost done. All the functionality has been written, now I need to clean everything up and write the documentation. Hex grids will be officially introduced in the 1.2.0 update, which I expect to release within the next week or, if something goes wrong, the week after. Unfortunately, due to all the work I have put into Grid Framework since the first release I cannot charge 15$ anymore, starting with 1.2.0 the price will be raised to 20$, so if you want a copy of Grid Framework, now is the time to get it. When I originally released Grid Framework there were still many loose ends and it was not integrated well into the workflow. When you downloaded it from the Asset Store you had to move files manually in place, there were no menu entries, you had to drag a script manually onto objects, there was no custom inspector panel, there was no rendering, no Vectrosity support and less examples included. Over the time I have been adressing all these shortcomings and improving, but none on its own felt like they were justifying a price increase. With hex grids I'm bringing in a major functionality update and I believe the 20$ price tag is still well justified. Of course anyone who has already purchased Grid Framework will get this and all future updates for free, that was the deal when I first launched it and nothing is going to change about that.


How about herring for lunch?

Another progress update: WorldToGrid and GridToWorld are now implemented. For those who don't know, those two functions convert a point's coordinates from world space to grid space, the coordinate system used to locate points relative to the grid's properties, and back. For rectangular grids it's a fairly simple idea, the grid can be represented as a standard Cartesian coordinate system. With hex grids that won't do it, you simply cannot force a hex grid into a cartesian coordinate system, you need to find something else. Fortunately there are several topologically identical possibilties whith easier, more intuitive coordinate systems. For the first release I have decided to use the herringbone pattern:

The vertices of this pattern are the faces of the hex grid. This means the central face has coordinates (0, 0, Z) and the face north-east of it has the coordinates (1, 0, Z). This way each single point of the hex grid can be canonically identified by its coordinates. "Canonically" means that no two points have the same coordinates and no two coordinates represent the same point. As a side effect this gives me an all new grid to work with, although the herringbone grid will have to wait until later before it gets the proper treatment.

This brings me almost concludes the hex grid development. The only things left now are the vertex matrix methods, testing and fixing everything to make sure it's reliable and then writing the documentation.


Trying to fit a square peg into a hex hole

The align feature has been giving me quite some headache lately. For small objects it's easy, just fit them inside the nearest hex. It gets more interesting once your object spans over more than one hex. Here is a screenshot from the game "Age of Wonders" for PC (I upscaled the image manually, AoW has a very low resolution)

As you can see the city goes over two hexes and no matter which of the two I click, I always select the city. I tried many ways of calculating a resonable way how to fit such an object into a hex grid, but no matter what I tried, it was bloated, had many cases and, worst of all, didn't really make any sense. The way Unity is designed is to work with rectangular objects which might be rotated. In a hex grid system everything is rotated, but only from our point of view, in terms of game logic everything is the normal way. This is what is causing problems, I'm trying to force one viewpoint into a different context.

So, what's the solution? I decided to go for the easiest and most intuitive approach: each object will be placed into the centre of its nearest hex. What about objects that need to go over two fields? In that case the user would have to set the pivot point manually, either in the 3D modelling aplication or in Unity by parenting the object to another object and placing them relative to each other so the pivot object is where you want the pivot point to be. In fact, this is exactly how the Age of Wonders editor is doing it.

You'll get a better idea of what I mean when you see it in action. In this video I'm assembling the structure directly inside the editor. Note that only the parent spheres have Rigidbodies, but all spheres have colliders and the script. Unity is designed in such a way that if an object has no rigidbody calling "rigidbody" will return the RB of its parent. Thus it's always as if I clicked the parent sphere when I click any sphere of a structure.

I think this is a good solution. Unless I somehow come up with a better way to do aligning this is what I'm going to stick with.


Grid Framework version 1.1.9 released

Surprise update! Version 1.1.9 just got approved and it contains quite a few changes:
  • NEW METHOD AlignVector3: lets you align a single point represented as a Vector3 instead of a Transform to a grid
  • added the ability to lock a certain axis when calling AlignTransform and AlignVector3
  • added a new constructor to both GFBoolVector3 and GFColorVector3 that lets you pass one parameter that gets applied to all components
  • you can now lock axes in the Grid Align Panel as well
  • aligning objects via the Grid Align Panel which already are in place won't do anything, meaning they won't create redundant Undo entries anymore
  • fixed an issue in GetVectrosityPointsSeperate
  • renamed the classes BoolVector3 and ColorVector3 to GFBoolVector3 and GFColorVector3 to avoid name collision
  • size has always been a member of GFGrid, not GFRectGrid, I fixed that mistake in the documentation
  • minor clode cleanup and removing redundant code
The first two are based on a user's suggestions, thank you for bringing those up. Previously when you wanted to align a Transform it would be aligned along all the axes, but now you can set certain axes to be left as they are (relative to the grid's local space). Also, instead of aligning a Transform you can also just align a Vector3 now, this is useful when you only need to calculate a position. You need to specify a scale, which was previously taken straight from the Transform, but I've set it to default to (1, 1, 1) so in most cases you won't have to think about it. Of course the Grid Align Panel lets you lock axes as well now. Since the option is passed as a GFBoolVector3 I added a new convenient constructor to the class that takes only one parameter and sets all entries to that. The same goes for GFColorVector3.

Another improvement is that objects which are already in place in the editor will be ignored by the Grid Align Panel when you try to align them. The reason for this is that before, if you had set the Autosnapping flag and clicked on an object that was already in place it would create an Undo entry even though you didn't see anything happening. Now there will be an Undo only if something happened.

The function GetVectorsityPointSeperate had been broken due to a few typos since release and I've only noticed it a few days ago. I guess no one was using it yet, so it went unnoticed for quite a while. It definitely works now.

The rest is just some under the hoods maintenance, moving code around, removing redundant parts, updating the documentation, the usual stuff. None of it has any impact on stability or performance, but it is important to keep things clean when I finally release the Hex Grids.

That's it for now, please enjoy the new features.


how to loop through a list and remove items

The other day I had the following problem: I had a list of Transfoms and I wanted to remove the entries that met a certain condition. This is what I had written:
 foreach(Transform trns in transformList){  
This gave me the following error message: InvalidOperationException: Collection was modified; enumeration operation may not execute.

This makes sense, I'm modifying the list I'm currently reading and there is no way I can be sure I'll catch all entries. There are three ways around this problem: The first is to use LINQ (C# only), the second is instead of removing the entries at once to store them in a separate list and then use that list in a second foreach-loop to remove the entries from the first list and the third solution is to use a for-loop. After some reseach I reached the conclusion that the for-loop is the fasted way to achieve the needed results. Here is the code:
 int counter = transformList.Count;  
 for(int i = 0; i <= counter - 1; i++){  
           i --; //reduce the indexer because we removed an entry from list  
           counter --; //reduce the counter since the list has become smaller  
First of all we need to know how many entries the list has initially. I could have used transformList.Count in the loop directly but this way I don't have to call the Count method for each iteration. Then we set up the loop, we start at index 0 and go to counter - 1 (because the index starts at 0 instead of 1). We perform our check and if it succeeds we remove the entry with index i. Since the list has now been shortened we need to reduce i because an item that has been at a position of 7 for example is now at position 6 (assuming that i is less or equal to 6 in this case). We also need to reduce our counter because the length of the list has been shortened as well.

As you can see the amount of lines has been doubled, while using LINQ would have left the code short. If you know that your list will always be small enough I'd go for the slower but shorter approach. In my case though I have no idea how large the list will eventually be, so using the for-loop makes perfect sense. I hope some of you find this useful in the future.


Hex Grids love Vectrosity

I got the Vectrosity support up and running for hex grids, see for yourself:

This turned out less painful than I expected, a nice change for once. On to the next task.


Vertex progress

Good news at last, I just finished the finding functions for vertices, both in grid space and in world space. Here is a screenshot where the yellow gizmo indicates the vertex closest to the grey sphere.

This may not seem like much, but being able to find faces, boxes and vertices is essential because the other functions rely on them. That's it for now, more updates to come soon.