Are Unity's Tile Features Good Enough to Make Real Games?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
should you be using unity's tile sets in 2021 is the feature out of the box something that you can use for your games or will you need to supplement it with some kind of third-party tool or extra coding work to get it to do what you want that's what we'll be talking about today [Music] so i make games and i've been doing that for about five years now pretty much full time this one here is called arrowbound it was released last year it's a portrait mode platformer for android and it's sort of a spin on the jump king formula where you work very hard to jump up very tedious towers the main character apollo is bound to his arrows so you get around by pulling down on the screen and slingshotting upwards when you release all of the games that i make are unity games and it's been my engine of choice since pretty much 2016. this one here is called throneless it's a game that i started working on in april and it's a tactics rpg that uses unity's isometric tileset support in fact all of my games so far have used unity's tile maps i guess that puts me in a position to talk about them with a little bit of authority not too much but this is my experience anyway so this game is my baby it's called insignia and i started working on it back in 2016. it's been a continued work of progress for a long time and it's been steadily growing as i've built my profile as a developer in fact just so you can get a sense of what i'm like as a dev it's a side scrolling action adventure with notes of nintendo games like pokemon and zelda you play as an apprentice blacksmith named armin as you sort of ascent on this quest outside of the kingdom to to protect it from this invasion armin makes his way from town to town doing some dungeoneering and learning to become a blacksmith there are lots of environments and tile sets and i've been refining my workflow for a long time so we can talk about that a little bit later so you're interested in making games with tile sets why well this is a pretty straightforward question and we can answer it the obvious reason is that it's a classic approach games featuring tile sets harken back to an era where most games were forced to use them due to memory restrictions or processing restrictions tile-based levels and mechanics are a staple for rpgs strategy games puzzles platformers and simulations as well tiles constrain the play space they create a structure for the player mechanically or visually which build a simpler vocabulary for the space this can lighten the complexity for movement path finding and also make room for complex rules like rpg combat so simpler movement simpler tiles simpler game space means more room for more complex stuff an example of this would be describing uh aoe for damage or knockback in a tile-based game being way more straightforward if we're talking entire integers versus floating point space tiles also constrain the design space so they make designing levels a lot easier and more visually consistent art resources can get reused they can be edited once and populate everywhere being more modular level geometry is much easier to manage and consistent units like jump height and jump distance are things that you can measure in tiles and basically manage them very easily when you're doing level design so if you know your character can jump up beyond four tiles any four tile jump should be doable so now you're invested how do we do this in 2021 what's the workflow like well it's been the same for a while we basically have three elements the first is palettes then maps and then how they integrate in the engine so tile palettes or tile sets are just graphic assets you can create them using any editor you want and unity's suite expects raster graphics with pixel art being a popular choice you can use paint you can use a sprite pixel edit photoshop whatever you want it's all the same once imported the graphics are then given metadata like collision information this process is usually tackled by the same solution that handles level editing unity tiled editor tilesetter ogmo editor ldtk these all do this job tile maps are the levels that you design with your tile sets creating these assets usually involves painting tiles into a scene to fabricate level geometry in the same software that's used to import the tile sets so you can either manually place each tile you can place geometry tiles that then get prettied up with auto tiling rules that you set up or you could procedurally place all the tiles if you're more into procter let's discuss how this is done in unity the first thing you want to do is import some sprites so say you're in a sprite and you're just done building this very beautiful tile set you can drag the exported file to png into unity into the project from here you'll be able to inspect it and you want to make sure that you've got the sprite mode set to multiple and the filter mode set to point from here you can go to window 2d and then the sprite editor the sprite editor window looks like this you can click slice in the top left and then define the cell size and press slice and unity will take care of the rest it'll slice it up into these nice subsprite tiles and when that's done they'll look like this in the inspector now let's create a tile palette underneath the option for the sprite editor is this 2d tile palette option once you've opened that up i like to put it next to my inspector click create new palette give it a name and tell unity where you want that to exist in the project and then you can just drag your entire sprite asset into the window and it'll create the tiles very easy so far now let's create a tile map so this lives in the scene you go game object 2d tile map and then rectangular for this case we're using rectangular because our sprite set is side scrolling side scrolling and top down use rectangular but you can also have hexagonal and isometric for those variants once this is done you'll see the grid and the tile map has two separate game objects nested inside one another on the left in the scene hierarchy this is now where you can start painting so you can just go to the bottom right press on one of the tiles press b and drag that around and there you go so you can then start creating your tile maps and they look beautiful if you want to create some collision information you can go back to the sprite editor and click on custom physics shape by default these are automatically set up and they fill the entire texture but if you're like me and you've created a tile set that has semi-filled tiles like these corner tiles you'll need to create the colliders yourself now this can be a little tedious as you can only inspect one tile at a time and you can't see the custom collision shapes on any of the other tiles so you'll need to draw the rectangles fill them in the space click on the adjacent tile and make sure that they're aligned you can copy and paste the shapes but you can't do it with the keyboard shortcuts you have to press copy and paste in the little buttons above the editor there it's a little finicky and it takes a little while but at least once you've got it set up it's done so you can then go to your tilemap game object throw a tilemap collider 2d on it and you'll see this if you want this to be a little more clean you can go to the grid and give it a composite collider 2d and that will take all of those edges that are sliced up and make them one uniform rectangle this is really important if you're making a platformer as the base collision system that unity uses i believe it's based on box 2d for the 2d physics has an issue where running over those creases uh has a tendency to create what are called ghost collisions so what will happen is your you know rectangular character controller collider as it crosses over the scene between those two there is a horizontal collision between the vertical face at the front of the character and the vertical crease that goes down within those tiles so the composite collider will fix that now you can throw a particle system in here or your character and you'll be able to run the thing with physics and it all works so if that's all your game needs then that's good enough and it's fairly straightforward there are scenarios where of course the bigger your game is you want more complex maps with complex rules so let's look at how unity handles that so insignia is a game that has a demand for advanced tools the game's character controls are quite capable and we can talk about those in relation to the tile map requirements the game has wall jumping it has ledge grabs there are fall through platforms that you can jump down and there are slopes and combat and traversal can take place on slopes between characters and npcs there are also different grades of slopes so there are square tiles one by one slopes and two by one slopes there are also tons of levels in insignia too many to place each tile manually as a solo developer given how detailed the environments are it's just i couldn't place all of those tiles by hand instead i have a prototype tile set that i use to paint the geometry this is then converted into the final appearance using auto tiling rules adding things like ledge triggers tags for walls and fall through platforms so let's discuss how we might do this in unity unity has some support for advanced rule tiles the feature essentially allows you to paint the geometry and through a series of rules the engine replaces the default block with a more suitable one for the context so the functionality doesn't come packaged with the default feature set in unity you have to download it from the package manager now i'd argue this is a really powerful tool and it's something that should come standard but you won't find it in a normal registry search instead you'll have to enable preview packages in the project settings bit of a red flag there so once you've enabled that you can find the rule tiles in the 2d tile map extras you can add a new rule tile by following this path create 2d tiles rule tile and this will create the asset when inspected it looks like this so the raw tile has a default texture which is then replaced by one of the rules below when the conditions for that rule are met each rule tile is defined by picking the output tile and then specifying when you want it to show up based on the neighboring tiles the green arrows mean there needs to be a tile in that direction the red x means there can be nothing in that direction the gray squares are undefined and can be whatever you want and so this rule turns the tile into a grass texture because it's covered on all sides except above where there's empty air it seems pretty good and with a nice looking pallet you can actually get pretty far with just one rule tile so at first when you click down you'll see nothing change but as you place more tiles you'll see the rules start to come into effect and very quickly this becomes clear that it's way faster than placing these by hand it's like a it's like magic so so far so good we can place a rule tile that covers all kinds of square blocks now let's figure out how to work in our slopes uh there is no rule based on proximity that we can define that covers places where we would only want to draw a slope that's not a square block now you could argue okay what about something like this so nothing in the side top corner or above and that would work but what if you wanted jagged blocks like this as well or even edges that aren't sloped this becomes a bit of an issue you can see it's the same rule either way so there's ambiguity there there's no way to define an obvious slope i think the logical option here would be to create a second rule that had the slopes at its center and for the user to just pick the slopes and start painting them with their own set of rules there's just one problem rule tiles don't recognize each other so a rule tile can only operate when it's adjacent to other instances of itself it doesn't look for empty air it looks for whether or not the tile next to it is a rule tile or not this basically destroys any hope we have of mixing and matching rules well okay maybe there are other ways around this so we have a few options here we have normal tiles that you just placed by hand we have animated tiles the rule tiles we've looked at isometric rules and hexagonal rules for different tile map perspectives we've got rule override tiles that looks like something advanced rule override tiles and then a custom rule tile script so lots and lots of options here but the problem is that none of these really do what we want as far as i've seen in the documentation and as far as i've tried with my experimentation all of these create sort of variants almost like prefab variants of rules that you set up and overrides for specific cases in those rules but none of them really allow you to mix and match rules so i have no doubt that there are other ways of doing this in unity with custom scripting anything's possible but why would you go to the effort of writing that functionality where there's actually a lot more that we need to be able to do that unity can't do yet and there are tools out there that do this already and much more so this is level designer toolkit and you can see here very very easy placing of different rules with lots of mixing and matching and special custom scenarios where those rule tiles meet each other it's very advanced very easy to use what's more tools like this actually do import directly into unity so the one that i use is called tiled and it can do all of that same stuff and it's also free so let me show you how it works this is the ui for tiled it's not so different from unity it has a scene a hierarchy a palette an inspector and what i do is i design a prototype dial set like i said that i use to paint the level geometry so that i can easily see what's going on you can see that i've got the base shapes set so i just paint slopes where i want slopes and i paint squares when i want squares converting these into the finished tiles involves defining a special map where all of the rules are defined as regions so there are still rules but these are set up a little bit differently to unities each region contains some prototype tiles configured in an arrangement where i want some particular output then on a layer above i paint what i want the output to be in the finished tile set so you can think of this as like a visual find and replace find purple tiles that look like this in this region and replace them with terrain that looks like this you can also use the finished tiles as inputs in new rules that then look for those repeated tiles and replace them with more natural ones so if i have a tile map that's nice and flat and i have my basic rules that define you know the grass rule that'll be all the same grass tile right what i can do is i can put that grass tile and the instances where there are multiples of them into a rule and output more natural ones like this i can also procedurally create those bridges with fall through platforms like this those are the rules and that's the output i've even defined boxes that get interpreted as ledge triggers when they get imported back into unity so here was my prototype and with one button that's the output looks really nice right importer scripts like super tiled to unity are free as well and they're also well supported and tools like this are really awesome because they treat the tiled file as a first class unity object you literally drag the map file into unity and then put it in the scene and that will be a container for unity's native tile maps so we're not overriding unity's tile maps or circumventing it with a completely different feature this is still unity tile maps but it's being managed by a tile map editor that's outside as such if you're entitled and you edit a bunch of stuff you press save if it's already in your unity scene it'll be re-imported automatically and update right there in the scene one other amazing feature that tiled has is its ability to view a collection of maps in a world as a single editor so i can zoom into any of these files here and start editing tiles on them as if they were one scene which is really helpful for visualizing dungeon layouts you can imagine how hard it is to keep all of these in different unity scenes and just have them indexed by name when there are likely to be a couple hundred in insignia as a side note i've actually started working towards smaller levels in unity rather than one large space part of this is because of performance so smaller tile sets are easier to load and easier to work with but also the bite-sized chunks of level design are easier to validate from a play testing perspective and i don't need to bind them to euclidean space i can just create a door at one level and then have the next level open up and i don't need to have these hallways that join the level design together you just fade out of one room and fade into the next okay but what if your tile sets aren't this ambitious what if you're not going for a setup where just to create some grass you've got like four tiles worth of content maybe there are some other things worth knowing about unity's tile set feature so let's look at the second case study infinite scrolling tiles harrowbound is a good example of a project that has simpler needs for the map designs but asks more of the system at runtime as you can see the tile sets are a lot simpler than insignias there are no custom colliders because the textures fill the whole rectangle there are no multi-tile rules so unity's stock tiles work just fine here the play area for each map is 10 by 18 tiles and the maps are stacked vertically into an arbitrarily large list i wanted to be able to effectively have an infinite scrolling set of levels and just procedurally shuffle the assets so that you know the player can just load into a new level seamlessly i even had plans for a level editor in the game that allows players to design their own screens mario maker style the original scope would be to allow them to share these with their friends with like qr style codes and you need to complete a level first before adding it to the list this was dog fooded so i actually designed the levels in the game editor for the rest of the game myself and i made a choice for the camera to never have to track or pan so this gives the player a fixed view of each level like jump king the way the gameplay is set up this can lead to some pretty catastrophic falls so if you fall multiple screens you need to load the tiles in very quickly so let's discuss how we might approach this in unity the first thing that i do whenever i'm in this scenario where infinite or scrolling comes up is i think about object pooling for those unfamiliar object pooling just means keeping objects around in memory for when you need them again rather than deleting them it's useful for when you have assets that are spawned by the player's actions or their movement at runtime a really good example of this would be the bullet holes in a game like counter-strike so rather than instantiate new whole sprites every time the player fires the gun you add them to a list and when the list is full you don't spawn in any new ones you just move the oldest bullet from its original position to the new position so you're reusing and recycling those assets here's the before and here's the after so the bullet holes on the left have actually started to disappear as the new bullet holes on the right appear so to do this with unity's tile sets what i want to be able to do is take some sort of tile object and move it somewhere else when i need a new screen to load in rather than delete that asset and create a new one from scratch unfortunately the unity tile map feature doesn't give you any access to the internal data structure that contains the tiles so you can't do any fun reorganization of tiles at runtime there's really just get and set there's no move unfortunately uh in any case any funny business with the rule tiles and composite colliders erase all chances of optimizing this process so if you were to move a tile anywhere removing it means refactoring all the tiles around it if you're using rule tiles and placing it again means refactoring the composite collider so i resign myself to having to deal with this the unity way and here are some steps that i did take to try to optimize this working against unity so option one is just don't have an infinite scroll if you can afford not to just load up a ton of data at the start and um you know take it away from there this will work maybe with a bit of a stutter on start but who wants to admit defeat the second is to load new screens on transition so delete and create whole screens at a time this is really inefficient and creates stuttering on every screen transition so we're talking about 180 tiles being deleted and 180 tiles being instantiated and then stitched together with a composite collider and then made you know into their rules and that's no good either multi-threading is probably an option here but i don't have a lot of experience with that and i don't know for sure that it wouldn't create other issues so i thought i'd stick with what i know option three which is what i went with was to stream new tiles for off-screen levels over time so i have an off-screen buffer and what this does is three or four screens away whenever we move i start loading in one at a time or a series of tiles at a time this can be done from such a distance away that it keeps up with the player's velocity and can be used basically infinitely it's low load on the cpu and low load on the memory so everybody wins you can see here on the left is my scene if i scroll out you can see we've got one two three either side and down here we don't have any level geometry loaded in because it's too far away if i drop off of the bottom of the screen so i'll pause it here and we'll start stepping one frame at a time as soon as i make my way off the screen one two three you can start to see the level geometry load in we don't have any collision data yet we just have the visuals and they're being loaded in over time and once it's done then we load in the composite collider nice so i did manage to sneak in some object pulling in a couple of ways one is with the colliders you can see that the colliders weren't loading straight away this is because i'm not using the colliders on the tiles because i don't have any control over the tiles themselves i just took the colliders out entirely and procedurally i place colliders wherever the tiles are being placed because they're managed by me i can actually just save them and recycle them later rather than delete them and instantiate them again i don't run them under the composite collider until they're all done as well i'm also placing these animated grass tiles that sit on top of the tiles procedurally and i have them pulled as well they're just sprites basically elements like these go really far in breaking up the monotony of a tile set too i have a pearl in noise space that moves from right to left over the terrain and that controls like the wind intensity so each grass sprite animates at a rate that increases and decreases based on that wind intensity this means that i don't have to make the grass reflect the direction of the wind and you can just follow based on the rustling of the grass the direction of the wind which i think is pretty natural looking and i was really happy with the result so that's how i got around streaming issues with unity's tile maps let's look at one more case study and this is for isometric 3d maps so throneless is a game that i started working on in april it's currently not in active development but at the time i've been playing around with unity's isometric tile set features and was interested to see how far i could take a game that was inspired by final fantasy tactics advance on the gba so let's look at thrones's tile requirements so final fantasy tactics advance is an isometric pixel art game although the assets are 2d you can traverse the maps in all three dimensions so there are elevations to the map so you can go forward back left right up and down which means that these are 3d spaces being represented by 2d sprites i wanted to recreate this format but in a more modern way so it was really important to me that players could interact naturally with these scenes i wanted the player to be able to select tiles and characters with the pointer with the mouse or their finger rather than shifting around a cursor in three dimensions with the arrow keys so let's look at how you can get a start on this in unity so unity does support this 3d tile map setup and you can access this by building an isometric z as y tile set you can paint on these the same way that you otherwise would but pressing the plus and minus keys will paint on a higher layer changing the z position property when it comes to selecting these tiles with the pointer unity does have a little set of methods that you can use in the camera and tile map classes first input.mouseposition returns a screen coordinate which is dependent on the resolution of the device [Music] luckily camera.screen2worldpoint will convert any screen coordinate to world space so now we can tap on the screen and get a corresponding world position from here we still need to convert this into tile space so the first port of call here would be normally to go for tilemap dot world to cell this function though is really designed for orthographic maps that's rectangular maps where the grid is aligned to the 2d world space this will actually return a correct value for isometric maps too but only at the ground level so that height stuff doesn't work and if your sprites are used to show depth in the z-axis it doesn't know that you're clicking on the sprites it's really just looking at the paper-thin ground level of the isometric space that's not what we want obviously we want to be able to click on the sprite and for the sprites tile to be lit up so let's think about how we worked around this in order to select the tiles through the screen i needed to roll my own little algorithm here the algorithm is a little difficult to explain first we need to appreciate how isometric projection works so any tile that's behind another tile relative to the camera appears above it but any tile that's on top of another tile also appears above it in the same position so behind and above visually are in the exact same physical space in the screen you can see here how trippy that is so when clicking on the screen we want the tile that's closest to the camera this algorithm effectively takes the world cell output and then reproduces a kind of raycast walking away from the camera towards that point on the isometric space one tile at a time and it checks every space along the way we keep stepping forward until the tile map says that it has a tile at the index that we're looking at and then we've hit the top we also need to factor in however the possibility that we could be selecting the side face of a neighboring tile which is in front and to the side of the one that we're looking at so we have to check the side that the pointer is closest to just in case and this is called like an offset selection in my algorithm so this creates a kind of like a zigzag raycast all the way up the result works really well and it took me and my twitch streams chat like two days to get the logic right you can see here i've also got pathing going on so there's some a-star in there as well and we can talk about that too for simplicity's sake in what is already a tricky perspective i decided to implement the pathfinding as a 2d a-star over the 3d map you can think of this as like melting cheese over the map and anything that the cheese touches that's part of the a star space this doesn't allow us to have characters standing on bridges while other characters stand directly beneath them but there are plenty of good reasons why we wouldn't want to do that anyway the challenge of spawning enemies and objects into the map was actually surprisingly solved using the same algorithm that i did for tile selection so if i just place a character visually where i want them to be standing and then check the tile at their feet using the same selection algorithm this would just return the correct tile so this means i could just drag and drop characters and prototype little battles out without having to worry about the perfect tile indices that they need to be standing on in x y and z space because of those perspective issues that i mentioned earlier it was actually really difficult to do a lot of the map editing and i was really intent for the player to not have to deal with this when they were playing so i wanted to resolve some of those topology issues you can see here it's almost impossible to understand whether the tiles in the middle are above or behind or next to the ones that are in the front so i looked at final fantasy tactics advanced and noticed that they were carefully placed outlines wherever there was a free edge this really helps break up the map and establish depth you can see here just you know wherever there's like a gap that's where we see an outline my first guess was to try to work in some kind of shader but i really wasn't too keen on doing a lot of those proximity checks in all the different directions to check where the outlines should be based on where the tiles were and then passing that from cpu land into the gpu i'm sure there's a solution there but it just didn't feel like the right direction i tried expanding the tile sprites out so that they were larger than they visually were so that i could do outside outlines rather than interior outlines as part of this process but that caused some funky sorting issues as well it's worth mentioning unity's sorting order for tiles is uh particularly with isometric tile sets really confusing for ui sorting order is established by hierarchy right so things that are further down show up in front for 3d objects the sorting is mostly handled by transform position related to camera and different render passes stuff like that for sprites we have the sorting order and we have the sorting layer and the tile maps use these too but only for the map as an entire object if we're talking about individual tiles and the way they get sorted these are ignored completely and the actual depth is determined by a custom axis that's set in the pipeline asset settings this only works if you multiply the y dimension by negative 0.5 and subtract 0.01 from that number this leaves you with an inverted sorting axis what that means is the further back you go into z-space away from the camera the closer to the camera the objects appear this is really unintuitive to inspect in 3d it makes debugging very difficult i imagine that the design decision here had to do with adding things in layers is something you naturally want to do but if adding things brought them closer to the camera and we were stepping by like one in-game world space unit every time very soon with most camera setups we'd be passing through the near clipping plane so the higher tiles would be invisible so instead rather than do that they push back away and the higher your tiles go the further back you just pull your clipping plane again not super intuitive understandable but i found instead a really kind of novel solution that i'm embarrassed to admit is not very computationally efficient but very easy to implement so i wanted outlines in four possible directions up down left and right first i duplicated the tileset four times then i tinted all the duplicates to black i push the tilemaps into the background so that their layers sit kind of between the normally textured ones and in my case this was setting their z position to negative one once i had them you know childed underneath the original tile map and then i offset each of them in one direction by one pixel so the left copy goes one pixel to the left the right copy goes one pixel to the right they're all just offset by a single pixel when this is done the blackened tile maps just happen to peek through wherever there's an empty edge creating a perfect outline they even respect the player position as they occupy the exact same space as the players remember these aren't outlines these are actual tiles and they're just sitting behind the normal tiles in the correct positions in space just slightly offset i know this isn't great practice but since throneless doesn't do any computational work with the tile sets at runtime this solution was totally good enough so let's look at some takeaways unity offers great tile set features that you'll almost definitely need to tinker with if you're going for something very base case and you're not doing any procedural work or any tile streaming and your levels are very small it's totally feasible to use the out of the box features that unity provides but if you have any ambition about making a game with tiles that stands out is of high quality has streaming or is complex in any way you'll almost certainly be getting your hands dirty i love working with unity and i can empathize with a lot of these design decisions that lead to the situations that i found myself in i kind of just talked this up to being the reality that unity is a game engine that's not made for a single game right these are general features there's very little incentive for unity to go finding these edge cases that developers will be running into uh and many of these features will have beta periods that last longer than the games that are being made with them that said i did start insignia in 2016 and the tilemap feature didn't even exist then so i'll wrap up this talk and and get back to work happy tiling and thanks for your time hey pal thanks for watching and thanks most especially to the patrons and twitch subs who support this channel and my gamedev project insignia to find out more click the links in the description below and if you like this video tell youtube by clicking the like button and then youtube will tell me and then i'll make more videos that's nice thanks again and until next time
Info
Channel: AdamCYounis
Views: 39,239
Rating: undefined out of 5
Keywords: game development, pixel art, game dev, game, video game, indie games, stream, tutorial, essay, unity, tilemaps, tileset
Id: wRkT10D-Quo
Channel Id: undefined
Length: 36min 20sec (2180 seconds)
Published: Sat Jul 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.