CrossyRoad is based on a grid system. The player can only move left/right. up/down. All obstacles and objects are based on a grid layout with the only exception being the floating logs that gradually move across the screen; however even with these, the player will snap to the nearest grid spot when jumping. As the new game will be based on this, the first job for me would be to come up with a grid system.

 

I didn’t want to over complicate the system, so the first thing I noted was what I would require from the system:

Grid Engine Attributes

  • Engine should provide methods to move objects (by providing new positions) to another grid space.
  • Allow checking of specific grid units for objects (to allow us to check for potential collisions before moving).
  • Allow objects to snap to grid spaces (should any objects become lost)
  • Constrain objects to the grid

With all the following objectives in mind, I set out to code a simple class that would cover what I needed.

The code is actually a bit of smoke and mirrors. The grid layout (as you can see in the header image) is drawn using gizmos in the editor window. This certainly looks like a grid, but in reality, the code isn’t actually drawing a grid; instead the grid gizmo is drawn using methods in the class to best represent what the grid spaces would look like. The best way to go through it is to describe some of the methods in the code:

Parameters

First of  there is the definition of some very important variables; these are the grid unit size and the size of the grid in the specified unit size. These variables are used in all the calculations to return the correct points. I made these accessible in the inspector for use in the design environment.

GetNearestUnitCenterPointOnGrid

Feed this routine the objects vector3 position that you want placing in the grid, and the function will return the nearest center point within the grid as a vector3. This essentially works by dividing the current position by the grid unit size. I also ignore any floating point precision, instead rounding to an integer to give the correct space. This will snap the object to the nearest point divisible by the unit size, and as such places it into a grid position.

GetNextUnitCenterPointOnGrid

Works exactly as above, but rather than returning the nearest point, it will check to ensure the object is in a correct position on the grid, before moving to the next space on the grid. The next space is dictated by passing in a direction to move (up, down, left, right and each diagonal corner).

getPositionWithinSingleUnit

The two above methods return the center point of the unit. This function can then be used to easily return a specific point within that unit. You can pass in a position in percentage for each x,y,z. For instance passing in 0,0,0% would return the bottom, left, nearest corner position.

checkForObjectsAtPostion

This is probably the heaviest function. Its the grid collision checking and by extension the collision checking method for the whole game. Essentially you feed in a vector3 position where you want to check for a collision. Lets say you want to move the player forward. Before you move the player forward, you would return what the forward units position would be using ‘GetNextUnitCenterPointOnGrid’ and then pass it into this function to check that space for an object. The function will return an array of objects (tags) that exist (or not) at that space. We can then decide if the object can be moved or not.

Gizomos

To further enhance the use of the grid system I added some gizmos to the editor window so I could see where the grid and more importantly the units are. The grid engine defaults a units origin position to exactly center; I also represented this center point with a gizmo. I then added the gizmo settings to the attributes window so they were more practical to use.

And the rest…

There are a few more helper functions thrown in there, but the above is the majority of the class.

The constrain to grid option is useful if you need to keep an object within the grid (and not allow outside). I’m still unsure if I will need to use this or not in the game.

 

No To Physics.

One of the earliest, and easiest decisions I made on the project was to avoid using physics. On a game like this, physics is a big overhead that is just not needed. If you break the game down, the player essentially just needs to move within a specified grid, and check for an object in the surrounding spaces; neither of which need physics.
The solutions to these would be found in my new grid system. The grid system will provide new vectors for the player to move to when requested, and can check specified grid spaces for collisions, returning what object is there if any.

 

Implementation

To keep everything as simple as possible I have set the grid size to be 1 Unity unit x 1 Unity unit. The main advantage of this is I don’t have to worry about floating point numbers. Also, for placing objects or checking where something is will be much easier; eg, If I want to place an object in the fifth row up, I can just use z=5 in the transform.
The grid will be based around 0,0,0 co-ordinates; again, just for ease. I also picked an arbitrary number of 10 units wide and 20 units on the z axis. This size will essentially be the play area, allowing the player to move 10 units sideways, and rendering at least 20 units worth of land in front of the player. This figure may need a bit of tweaking. As they player can move backwards to some degree, there always need to be land in front and behind the player. I have decided that the land either side will stop at the 10 units; not quite sure how I will achieve the theming to make the abrupt end to the land work yet…

Releasing

As the grid engine will be a useful tool for many games/objects, I do plan on releasing the code on my bitbucket as opensource; and maybe possibly a unity asset. I’m not sure when this will be, more likely when this project has concluded and any further iterations completed. If anyone is interested in the mean time feel free to get in touch to discuss.

Leave a Reply