InGame Tilemap Editing - 2D Level Editor with Unity - Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
do you enjoy drawing nice tile maps well maybe your players would do this too that intro sucked in this tutorial series you will learn how you can create an in-game ui where your players can draw on a grid we are going to use unity style maps and there will be a lot of coding involved so you should know the basics of unity and about coding with unity but i am also going to explain a lot here you can see the content of the currently planned parts for this series so let's not waste any time i start with a new 2d project i already made some example tiles which are inspired by rimworld let's start by preparing the tiles i add the image to my sprites folder and adjust the settings as needed i can slice this image by cell size with a size of hundred by hundred every box is now a single sprite if you use your own sprites just make sure that every sprite has the same size but like the door here it can have transparent parts since we want to draw on a tile map later on i will create one a default one after creating a tile map you can open the tile palette editor by clicking this icon right here this will be only shown where the tile map is selected create a new palette which will be only used for our items which are buildable for a user now drag and drop your tiles into the palette doing this the first time you will be asked where to save the resulting tiles i create a tiles folder therefore check if you can paint with your tiles on your tile map and that everything matches so those are the tiles we want to be able to draw with later during runtime for this step we will work with so called objects these are objects row structure is defined once by code and from which you then can create the specific objects manually or by code in our case we create them manually and thus decide which building objects are available at first we need a folder for all our scripts now let's create a script which will define the structure or the base of our building objects the name of your script and therefore the generated class name will define what your objects are you can remove those two methods now it's important that this class derives from scriptable object not from monobehaviour if this is done you can add this line which will create an entry in the create context menu so that we can create objects from this class by using the unity interface for now we want three properties for every buildable object the name where we will simply use the file name the category this item belongs to and the according tile base so what exactly will be drawn onto the time map later on for the category i will simply create an enum which holds two values wall and floor and even if the door might seem different it is really similar to a wall so it will belong to this category now let's create two serialized fields one for the category and one for the tilebase so we can set the values of those variables from the unity ui that other scripts have access to those variables i also add public getters which will just return the private variable this is everything for here now back in unity i will expand our folder structure i create a folder scriptables where every scripted object we are going to create will be in to be more specific i create a folder in there called buildables so we can place all our building objects in there to give it even more structure i create folders for different kinds of buildables but this is not coder category related just my personal style questions feedback or just urge to talk join my discord when you now right click and go to create you can see the entry we defined in the building object base script you can create an object of this type like i said we are going to use the file ms universal name so if you are going to work within i18n you might need a separate field for this my two serialized attributes are now ready to be filled for the category it already selected the first entry which fits here to select the tile base you can either click on the point button here but this comes without previews so it's better to select your tires folder and drag and drop the needed tile into the slot i will do this for some examples and i also recommend you to just use a few examples for now because we will expand those attributes here later on and you don't want to repeat this for every one of your objects now that we know we have walls and floors it just makes sense to have those tiles on different tile maps something like this a separate map for the walls and one for the floor but doing this manually is way too inefficient how to automate this will be shown in the upcoming next video so don't worry don't create this i just forgot to delete them we will do everything on the default map but what we are going to create manually and automate later is the ui the user must be able to select whatever he wants to draw before he can draw yeah for this we will add a canvas to our scene i make it scale to the screen size with a 1080p resolution i create an empty game object for the overall overlay which i span in the lower left corner so the build ui will always be visible there now i want a wrapper for my categories note that those categories here are mainly for decorative purpose just what the user can see this doesn't have to match to the categories from descriptible objects add a vertical layout group to automatically align all those categories i want the anchor to be on the bottom left corner and remove the checkboxes for child force expand and then create an empty game object again for one category the category itself will have a background which is just right for now and a text i'll give this just an example look feel free to design this your own way i add a horizontal layout group to the category and set the text as a child of the background on the same level i create a new empty game object again for the items which will belong to this category a horizontal layout group will help us aligning the entries remove the child force expand checkboxes here as well for this wall there will be two wall objects we created earlier but i don't name them explicitly now an image component lets the player see what they cancel licked you can select an image by clicking the circle icon to the right be aware that this field wants a sprite which is not one of the tiles we created earlier but rather those single entries in your sprites folder i repeat those steps for our other examples the floors and the door the latter one will be grouped as item so that you can see there is no reference to the other category where we selected wall so what do we want to achieve now the user clicks on one of the items and the according tile gets selected and the user can draw it the click event itself is easily handled by adding a button component to those items so let's do this first on one of our items and choose the wooden wall for now we could now use the default unclick handler but this is where the second part comes to play how do we know what we clicked currently we only know this is the wooden wall because of the sprite we can see but the sprite is just loosely connected to our created building object which is the real wooden wall we want so i'm using a different approach i create a new script called building button handler we need to import the unity engine.ui package so we want the connection between the ui object and according building object base that's why we need a serialized field for this i also want to reference the button for the item where the script will be located in the awake function i get the button component and assign it to the button variable when the button gets clicked i want to call my button clicked method and for now i just locked that it was clicked and show the according building object by referencing the name attribute we will print the file name that's it in the script for now now i just add a script to my wooden wall object and assign the building object base now we know for sure this is the real wooden wall not just a sprite in the ui repeat adding the button and the script as well as selecting the recording object for your other items when i now start the game and click one of my buttons i can see the output of the console it shows the according object and of course also detects the click event successfully a little information for you i will showcase different things you can improve with this base idea but of course creating a really nice and even powerful level builder is way too big but if you have wishes or ideas besides the hero listed points which will be done in the upcoming episodes let me know in the comments or join my discord i definitely planning on doing some updates based on your wishes now that we can select items we want to draw them onto a tile map besides the click event on the button we must now be able to detect player clicks for placing a tile map and for the next video also hold events those of you who know my videos know that i usually use unity's new input system so of course i'm going to use it in this tutorial as well but if you know what you do with the old one you should not have problems adapting this approach install it by going to window package manager select unity registry and find the package called input system during installation you have to accept the prompt and unity will also restart even if you haven't used new input system before you will still be able to follow along but for more detailed explanations about the why watch my tutorial series about this topic i create a folder for the inputs and in there my input action file inside my action map gameplay i am going to add three input events the first and the second one will be left and right mouse click it's from the default action type button the third one is the current mouse position select value as action type and vector 2 as control type don't forget to save and that's it for our inputs i prefer working with inputs as c-sharp classes so hit the checkbox to generate one change the file path so that it gets generated into your scripts folder and click apply in your scripts folder is now a new script named like your input action file since we already created a canvas to automatically added the event system to your hierarchy after switching to the new input system you just need to check this button to switch it over to the new one now we can start a building process let's add a script for this i call it building creator to give this code a professional look i am going to use singles well no i use them because i like them and they fit you but don't worry you just need to copy a script into your scripts folder i use a little adapted version of the one ngames provides with this tutorial but you can't just use the one from him or mine it's linked in the description if you want to know more about singletons you can watch the video it's also linked in the description drag the script into your scripts folder and like i said that is everything you have to do with it now open your building creator script the singleton class already derives from monobehaviour so it's fine for us to derive from singleton give your current class name as type for the singleton and we will later need the unity engine dot input system package so add this to your imports since we generated a c-sharp class for our input action we can now declare a variable of player input if you named your generated script differently you must change the type here due to the use of the singleton the awake function looks a little bit different we use the axis modifier protected like it is in the singleton script and add the keyword override to make sure the original awake function still gets called you need to add base.awake so manually call the awake function from the class we derived from now we can instantiate a new object of class player input inside your on enable and on disable functions you can now enable or disable your inputs now we can add methods that will do something if one of the defined inputs is triggered let's start with the mouse position i declare a vector2 variable for the current position whenever the mouse gets moved this variable gets updated add this on mouse move method the parameter is the current context of the input action from this variable you can redirect the two value which we defined earlier with the read value method and save it into your mouse pause variable in the on enable function we now tell unity to call this method whenever the input mouse position has a performed event in the on disable method we will remove the method call this avoids potential memory leaks now let's do the equivalent for the left and right mouse click we will also react on the perform event which is the best for simple click events but i won't do anything in this method for now just that they are there currently we have the ability to click an icon and know the according tile but the information is in the building button handler script to get it inside our building creator script we create a public method which can be called from the button handler the parameter of type building object base will be written in a variable but since it might be possible later that we want to change or reset several things when this variable gets changed i create a setter and only change to value we add this setter the setter is written with a capital first letter so i just need to change this part in my object selected method so what will happen now wherever the mouse is i want the tile it's currently located in to show the preview of the selected tile when i then left click the tile should be drawn onto the tilemap by right clicking i deselect the current item and there should not be any preview so this means besides the tile maps the objects get drawn onto we need a preview tile map we can draw the selected object onto this tile map and remove it as needed i add a serialized field for this preview map to work with tilemaps we need to import the according package i create a separate variable for the tile base variable from the selected object so that it's easier available and i also need two vector3 int variables for the grid positions the first one is the position on our tire map the mouse currently hovers and the second one where it was before so that we can delete what we have drawn there at last i add a variable for the camera and assign the value of camera main to it let's do something with the variables inside the update method i am going to transform the current mouse position which is saved inside the mouse pause variable to its world position with this world position i can now go to the preview tile map and ask which cell this position is in if this cell is different than the value of our current grid position i will save to all the value to the according variable and replace it with the new position so now i know always which cell my mouse is located in as well as the previous cell from this point on i can update the preview this will happen in an extra function what we want to achieve here is to remove the tile which is on the previous cell and therefore set a new tile on our current position this can be easily done with the set tile method the first parameter is the position and the second one the tile base a tile base of null removes any previous tiles from this position but currently all the calculations inside the update function also happen if nothing is selected so let's add a simple if statement which checks if there even is an object selected and since we decided to use the tilebase in a separate variable we need to fill this variable whenever selected object changes that's why it's handy to use etc here with a ternary operator i check if selected object is not null if it is not null i get a tilebase variable else i set the value of the local tilebase variable to null and we will also call the update preview method here so we can make sure any drawn preview tile will get instantly replaced with the new tile we can now prepare to test the script up to this point at first we need to connect the building button handler with the building creator i add a variable to save the reference of the building creator instance and assign the value in the awake method this process here only works this way because we use the singleton now i can call the public method we created and pass the building object base which belongs to this button to the building creator where it is saved is currently selected object back in unity we need to add a new tile map the preview map i also add an empty game object which will hold all our global scripts this is the place where we add the building creator script now we just need to assign the preview map to the according slot and can test everything i can select an item and we have a preview for every tile where we are the preview tile changes its position as long as i move inside the same cell range nothing gets changed if something is not working for you we watch and make sure you made everything correctly and if you are tired from all the code it's fine that was the biggest part now we just need to place the tile onto the correct tile map when clicking left or resetting the selected object by clicking right let's start with the latter one it's really easy back inside the building creator script i jump to the still empty function which gets triggered when we click the right mouse button now i can simply set the value of the selected object to null make sure to use the zetter by writing it with the capital s if the value was now before it doesn't bother so no additional if statements needed when something was selected and i click the right mouse button the preview gets completely cleaned like i said easy-peasy for now we want to try everything on the default map so we need a reference for this as well i then add a new method which will handle all our drawings in the next episode i will show you how to draw lines and squares but for now the only thing this method can do is call another one the draw item method is responsible for drawing a simple item on click so all we need to do is setting the tile base to the current position in our default map for now we just need to call the handle drawing method on left click but of course this only makes sense when we have something selected or else this would erase the click tile which is not what we want there is also another problem clicking a new button when something is selected also draws a new tile but this can be easily fixed import the unityengine.event systems package now we can expand the if statement we will check if the mouse is over a game object which interacts with the event system like a button and we only want to draw when this is not the case that's it back in unity you need to assign the default map to its slot now we can left click and the tile kind of stays at the position it is drawn onto the default map this can also be seen here because the preview map gets rendered behind the default map the preview disappears others can be easily fixed by setting the order and layer value of the preview map to something high so now you can draw simple things unfortunately you can't stack them like a green floor with a door on top so that's where one of the following parts comes to play so stay tuned thank you for watching and also thank you to everyone supporting me and the channel special thanks to my supporters and patreon patrick and izaray as a special thank you for you being the first one supporting me and thinking my content is valuable enough to support it financially thank you all and as usual if you enjoy the content consider liking and subscribing and i'll see you next time
Info
Channel: Velvary
Views: 1,948
Rating: undefined out of 5
Keywords:
Id: hx3ieBzVNg0
Channel Id: undefined
Length: 24min 4sec (1444 seconds)
Published: Sat Jul 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.