-
Notifications
You must be signed in to change notification settings - Fork 0
Grid & tile help
Levels are created upon a grid system which is loaded from disk. The grid is of fixed size, and represented in editor by a checkerboard sprite. You can click on this grid to see tile X,Y locations in the Unity editor, as well as extra debug information such as pathability and prop coverage.
While the grid is not a singleton, it can be accessed from anywhere using the level manager. As the grid is loaded from disk, the system is asynchronous: be aware of this when writing scripts that query it. You can subscribe to the LevelManager.Instance.LevelLoadCompleted delegate, which will allow you to execute code after the level has loaded into the grid.
The grid dimensions are hard-set in the editor and are currently not intended to be changed. While not intended to be changed, this is possible - however doing so will block you from loading any previously created levels that don't match the new size. You can query LevelManager.Instance.Grid.GridTileDims to get a Vector2 containing the grid's X & Y tile counts, which should be used instead of assuming the current values will stick through production.
The grid is a 2D set of tiles. Each tile contains its own metadata, as well as objects within it. To access a tile, you can query LevelManager.Instance.Grid.AllTiles - this returns a List of all tile objects. Additional functionality is provided by the grid, which may be helpful for finding tiles at a given location, or neighbouring other tiles.
A tile within the grid exists whether it is a part of the map or not - this is an important point to remember! If a tile is "unoccupied", the tile is simply a void space which has not been used in the map design. If a tile is "occupied", it will contain a reference to the occupying object, which is the map tile itself (containing the sprite and tile type information). Think of it this way: the grid could be 30x30, but the actual map may only use 10x10 - those 10x10 tiles are considered "occupied", while the rest are "unoccupied".
As well as the notion of a tile being occupied, tiles can also have props. Props are separate entities that render above the occupier, and are intended to be used for additive details to a tile (E.G. a vending machine, or a puddle). Props allow for extra functionality to standard tiles such as events, waypoints, and more.
Tiles contain a series of information that is useful for monitoring gameplay. This includes:
-
Dimensions- a Vector2 object of the tile's X&Y dimensions. -
Position- a Vector2 object of the tile's X&Y position in 2D world space. -
IsOccupied- a bool which is true if the tile is occupied by a tile object (E.G. a wall, the floor, etc). -
Occupier- ifIsOccupiedis true, this will return theLevelTileEntitywhich occupies the tile. -
HasProp- a bool which is true if the tile has a prop object (E.G. a vending machine). -
Prop- ifHasPropis true, this will return theLevelPropEntitywhich is on top of the tile. -
HasPropOrigin- a bool which is true if this tile has the origin of a prop. Some bigger props cover multiple tiles, so finding their origin may be useful for things like waypoints, where you'd want to path to an instance of a prop, rather than every tile it covers. -
GridPos- a Vector2 object of the tile's X&Y position relative to the grid. -
Index- the index of the tile in the grid array.
Individual tiles contain some functionality which may be of use:
-
SetOccupied()- this is ONLY to be used by the level editor, and level loading system. -
SetProp()- this is ONLY to be used by the level editor, and level loading system. -
SetPropOrigin()- this is ONLY to be used by the level editor, and level loading system. -
Contains()- call this function to check if a given point is within the tile (in 2D world space). -
HasNeighbours()- call this function to see if the tile has any occupied neighbouring tiles. -
IsAtTop()- call this function to see if the tile is at the very top of the grid.
The grid itself has some in-built functionality (aside from its debugging gizmos) that may be useful:
-
GetTileAtPosition()- call this to get the tile which covers the given position (in 2D world space). -
GetTileAtGridPos()- this performs the same functionality asGetTileAtPosition, however works on grid space not world space. -
GetTileNeighbours()- call this with a tile object to return an array of neighbours, which can be used nicely with theTileNeighbourenum. Be aware, if a tile is at the edge of the grid, a neighbour reference may be null, so handle this in your code. -
GetNeighboursFromBounds()- this returns an array of tiles around a tile given bounds information (the array includes the original tile at index 0). -
ClearGrid()- this is ONLY to be used by the level editor, and level loading system.
If a tile is occupied (see tile metadata above), you will be able to get properties of the occupier. The same goes for props. This property information will be useful to drive gameplay systems, such as fire spreading.
Tile occupiers are of type LevelTileEntity, and props are of type LevelPropEntity. Both of these classes contain the parameter Type, which is what you will need to use in order to query the tile/prop parameter databases. (They also both contain a parameter RenderOrder for returning their sprite's current sorting order, and a function Initialise for spawning them in the grid. If instantiating a prop, this Initialise function should be used instead of calling SetProp on the grid, as Initialise will handle all of this for you correctly. LevelPropEntity also contains rotation information, and functionality to rotate it after being spawned. Please note: props that are rotated after they are spawned may cause issues. Their colliders will update to represent the new rotation, however the tiles they occupy will remain as they were at their original rotation - this is due to the fact that a rotated prop may not fit the environment, and would therefore destroy itself. Please ONLY edit use rotation at runtime if you are aware of the potential consequences, or the prop is designed to work around that (e.g. doors).
In this example, we are querying the level's grid for a tile at X/Y location position and getting the type of the tile within it. This code assumes prior checks for tile IsOccupied and the level/grid being loaded: LevelManager.Instance.Grid.GetTileAtPosition(position).Occupier.Type.
With the Type acquired, we can now get its properties. To do this, you can use the TileProperties static class. This class has data which is populated asynchronously, and so you should check TileProperties.Loaded before querying it.
When Loaded, TileProperties provides functionality for:
-
GetDescription()- given aType, this will return the tile's description string. -
GetSpriteSet()- given aType, this will return a set of sprites and their bounds for use on the tile. -
IsPathable()- given aType, this will return true if the tile is pathable. -
IsFlammable()- given aType, this will return true if the tile is flammable. -
AllowsProps()- given aType, this will return true if the tile supports props. -
GetVariant()- given aType, this will return aTileVariantenum value to tell you if the tile is ofWALLorFLOORvariant. -
GetUseage()- given aType, this will return aTileUseageenum value to tell you if the tile is forINTERIORorEXTERIORuseage. -
GetZOffset()- given aType, this will return an integer to be used for offsetting the tile's rendering order. -
IsVisibleInEditor()- given aType, this will return true if the tile should show in the level editor UI.
A similar system is in place for props. Using a similar example to above, here we will get a tile at a given position, and grab its prop (assuming prior checks for being occupied, and having a prop): LevelManager.Instance.Grid.GetTileAtPosition(position).Prop.Type.
With the prop's type, you can now query the PropProperties static class (after waiting for it to be Loaded), with any of this functionality:
-
GetDescription()- given aType, this will return the prop's description string. -
GetSpriteSet()- given aType, this will return a set of sprites for use on the prop. -
IsScriptedObject()- given aType, this will return true if the prop is a scripted object. -
GetScriptClassName()- given aType, this will return a string matching the name of the script's class (ifIsScriptedObject). You can convert this string to the actual class using reflection, withSystem.Type.GetType(). -
IsWaypoint()- given aType, this will return true if the prop is a waypoint. -
GetWaypointTarget()- given aType, this will return aPropWaypointUserenum value to represent the user of the waypoint (ifIsWaypoint). -
GetWaypointType()- given aType, this will return aPropWaypointTypeenum value to represent the type of the waypoint (ifIsWaypoint). -
IsPOI()- given aType, this will return true if the prop is a point of interest. -
GetPOIType()- given aType, this will return aPoiPointenum value to represent the type of POI for this prop. -
GetPOIGoonCount()- given aType, this will return an integer representing the maximum number of goons that can use this POI concurrently. -
GetPlacementLocation()- given aType, this will return aPropPlacementenum value to represent its intended location (INTERIORorEXTERIOR). -
IsUnpathable()- given aType, this will return true if the prop's tile should be considered unpathable. -
IsVisibleInEditor()- given aType, this will return true if the prop should show in the level editor UI. -
GetZOffset()- given aType, this will return the prop's unique z-order offset value.
Tile waypoints are intended to be used for vehicles - for example, the GOON_BATTLEBUS should spawn on the START waypoint type, drop students off on the MIDDLE waypoint type, and then exit the level on the END waypoint type.
The GOON END waypoint is handled as the victory marker in levels.
New tile and prop types can be added using the DWB Toolkit in the root of the repo. This tool allows creation of props and tiles, and management of their sprites and metadata once created.
The tool writes to a proprietary binary format which can get jumbled in Git merges, so please refrain from adding or modifying any tiles or props unless given explicit permission by other members of the team. Deleting props or tiles can cause SERIOUS implications for maps that utilise them: it is recommended that you mark a tile or prop as "deprecated" in its configuration - this will hide it in editor, but allow backwards compatibility for older maps.