Tower Defense Tutorial – Brackeys – Ep. 27

March 7, 2019

Tower Defense Tutorial

Episode 27 – Unlock Levels

Youtube – How to make a Tower Defense Game (E27 UNLOCK LEVELS) – Unity Tutorial

By: Brackeys
Ep. 27

This tutorial gets into creating a system for locking/unlocking levels.

We started by going into our LevelSelector script and creating an array of UI Buttons. This would hold all of the buttons that allow you to select a specific level on the level select screen. We then added a for loop to go through all of these buttons and intitialize them as non-interactible buttons.

To go along with making the buttons non-interactible, we added a Button Disable animation. This was a simple animation that makes the button much more faded out than normal to make it clear that it is non-interactible. To make sure this effect is removed in an interactable state, we added an alpha animation for every other button animation state to just set the alpha back to 1.

Next we needed a way to keep track of the player’s progress to determine what levels they have access to. We wanted this to persist even if the player closes the game, so static variables are not enough. To do this, we need to save data out to a file. We used Unity’s player prefs as the simplest way to do this. We started by creating an int levelReached, which uses PlayerPrefs to GetInt levelReached. When using a get variable command, you also specific a default value to use if there is nothing associated with this value currently (i.e. this is the first time the player is playing the game), so we set that to one so the player will always have access to level 1 initially.

Now we setup that initial for loop that was just disabling every button to only disable buttons if their index (+1) is greater than the levelReached variable. The levelReached variable is now set at the end of a level if the player completes it, increasing the possible level options.

In testing the level select setup, they discovered the bug I mentioned as a possible issue in a previous tutorial. You can sometimes get a scenario where the enemiesAlive in the middle of a wave reaches 0, which signals to our system that the wave is over, even though there are actually more enemies left in the wave. They ended up using my suggested solution as well: just set the enemiesAlive variable equal to the total number of enemies in the wave at the very start of the wave.

They then go over some issues with modifying the game in its current setup. The changes we made in the Game Manager only apply to the current scene, so they have to be redone in every other level (or since we don’t have anything yet, delete the current ones and duplicate the updated level scene). The simple work around for this was to make objects like the GameManager a prefab so when you update it in one scene, it will be updated for every scene. Then, for an even stronger method they suggest is that Unity allows you to put everything that is repeated in each level into its own scene, and only the objects that actually change between levels are their own scene.

SUMMARY

  • Look into serialization for saving player data; many more advanced games use .json or .xml to store player date
  • Unity uses Player Prefs to do a very simple version of saving data
  • When using get/set variables, make sure to use the EXACT SAME identifier name for the variable. This will not generally return an error if entered incorrectly as it will just set it to the default value instead.
  • Unity has a system to let you load different scenes in at once, look into properly using this feature (this was the suggested ideal method if you want to create a lot of levels)

Tower Defense Tutorial – Brackeys – Ep. 26

March 6, 2019

Tower Defense Tutorial

Episode 26 – Fading

Youtube – How to make a Tower Defense Game (E26 LEVEL SELECT) – Unity Tutorial

By: Brackeys
Ep. 26

This tutorial gets into creating a level select menu for the player.

This would require its own scene, so we duplicated the Main Menu scene as a place to start since it’s already fairly empty. We started by setting up the hierarchy of UI assets for the level content selection area. It was noted that this is a general way to setup a scrolling menu for selecting objects in Unity.

The hierarchy is as follows:

  • UICanvas
    • Title
    • Levels
      • ScrollRect
        • Content

We then added a button to our Content UI object, and gave that object a Grid Layout component. This allows Unity to place everything in an even grid layout for you. We also added a Content Size Fitter. This helps allow the object it is attached to scale to fit the content placed in it. We also made sure to move the pivot anchor point of this UI object to the top of the object to make sure it scales downward from that point instead of out from the center.

We added a bunch of buttons to help see that all of the scaling and clipping was working properly with the UI elements. To help keep them from flowing out of the menu (which also works with the idea of creating a scrolling menu), we added a Rect Mask 2D component to the ScrollRect object which blocked out child objects that were not within this rectangle space.

Speaking of scrolling, we added the Scroll Rect component to the ScrollRect object next. This just required dragging in the ScrollRect object as the viewport and the Content object as the content to start this working. This did have a slight issue for me where it seemed that I could only scroll if I clicked/held on a button in the content area. If I clicked/held on an empty space within the content area, I could not scroll the menu, so that would have to be fixed.

We created a simple LevelSelector script and placed it in an empty gameobject. This script provides the method for the onclick event for each of the buttons to reference to take the player to the corresponding level. To help test this, we just duplicated our initial level and changed the number of lives to create a level 2.

Finally, we added a scrollbar component to the Levels object to go along with the scrolling of our scroll rect. It just gives another, clearer option for scrolling, especially for someone using a computer.

SUMMARY

  • Check pivot/anchor point locations for scaling UI elements, especially those using a component like Content Size Fitter.
  • Implementing scrolling into UI elements in Unity is straightforward with ScrollRect and Scrollbar components.

Tower Defense Tutorial – Brackeys – Ep. 25

March 5, 2019

Tower Defense Tutorial

Episode 25 – Fading

Youtube – How to make a Tower Defense Game (E25 WAVE SPAWNER 2.0) – Unity Tutorial

By: Brackeys
Ep. 25

This tutorial focuses on updating the wave spawner to be a more useful and versatile tool.

One of the first changes was to have the next wave spawn some time after the previous wave has been killed off instead of having it on an overall set counter. We create a public static int, EnemiesAlive, to constantly hold this value of how many enemies are alive in the current wave. We then let the Die method in the Enemy script and the EndPath method in the EnemyMovement script remove one from this value before destroying the enemy object. Since we are already referencing this in multiple somewhat unrelated areas, I think there might be a nicer way to reference one method somewhere that destroys the enemy gameobject as well as removing one from this global counter.

Another issue I am already noting here are that there might be strange cases where the enemy is killed almost immediately upon leaving the spawn, so enemies will be 0 already at that time and this may start the next wave spawning. It may be better to have the system just know how many enemies will be in the wave ahead of time and set the EnemiesAlive value to that at the very start of the wave, then subtract from this value when enemies are destroyed and let the next wave start when that value is 0.

Currently the WaveSpawner only holds a single enemy prefab to be the enemy to spawn. As most tower defense games do, we want to have a system that can spawn multiple types of enemies. To begin, we created a new Wave Class to hold the information needed for any particular wave. Since this is its own unique class, make sure to remove the Monobehaviour tag from the class. We also added [System.Serializable] to this class so it would show up in the editor. The values we created for this were:

  • public GameObject enemy – to hold the enemy prefab to spawn for this wave
  • public int count – to determine the number of enemies to spawn in this wave
  • public float rate – how fast each individual enemy in the wave spawns (1 over time between spawns)

To continue on the thought that we want to be able to have control over the individual waves, including having different enemy types, we created an array in our WaveSpawner script to replace the single enemy prefab gameObject we had before. This array would also be an array of the Wave class instead of gameObjects.

”It’s not as automated… but it gives us so much more configuration possibilities and really allows us to create something that’s much more fun for the end user. Having this idea of a wave that is kind of an object that we’ve created on our own with these different characteristics, then storing a bunch of these waves in a list, then going through them one by one and using some of the properties in there to create different behaviors is kind of the core of object oriented programming.”

Now our IEnumerator method SpawnWave grabs the next Wave in our array of Waves and uses all of its information. The enemy prefab was replaced with wave.enemy, the time between spawns was replaced with 1/wave.rate, and the number of times to go through the for loop was changed to wave.count.

Finally, to take advantage of this new system, we created some new enemy types, Tough and Fast, to go with our existing enemy which is now just the Simple enemy type. We created an entire Enemy folder, then gave each type of enemy their own folder to hold the gameObject prefab, the material, and the particle system death effect for that specific enemy. This seems like an effective organizational pattern to follow for holding different enemy types.

To edit the individual waves we want to create, we currently did that in the editor. In our WaveSpawner script, since we made the Wave class serializable, we could see our Wave array along with all the individual public variables associated with the individual waves in the array. We had to go to each one specifically to enter the enemy prefab for that wave, the number of enemies to spawn, and the rate at which they spawn. While this does give us a lot of control, there may be efficient ways to automate some of this process for longer scaled gameplay.

LEARNING PRACTICE

Good practice for learning to use your own classes: create a pretty basic method for a core functionality (like our spawner), then try to replace some of the main variables in it with those in a user defined class you make (like our Wave variables that replaced those in the spawner script). This is basically what we did in this tutorial since we had a very bare bones spawner but then updated it to work better with various types of enemies instead of just one. It really helped me understand, not only how to use a user defined class, but also how to effectively set one up.

SUMMARY

  • Keycode Shortcut – Visual Studio: with a piece of code highlighted, hold Alt + arrow key to move that code up or down a line
  • When you know you will create a lot of a certain type of object, creating a class that holds the key properties for that type of object is necessary
  • Newer versions of Unity allow for Prefab variations which might be worth looking into for our enemy prefabs (New duplicated versions worked fine for now though)

Tower Defense Tutorial – Brackeys – Ep. 24

March 4, 2019

Tower Defense Tutorial

Episode 24 – Fading

Youtube – How to make a Tower Defense Game (E24 FADING) – Unity Tutorial

By: Brackeys
Ep. 24

This tutorial focuses on creating an overall fading effect for the game.

We created an empty gameObject, SceneFader, and added a UI Canvas to that, which we then added a UI image to that is just a black image.

Then we added a SceneFader script to our SceneFader object to handle the fade effects. We used IEnumerators to handle the fading methods. We used the IEnumerator for its ability to wait certain amounts of time. The IEnumerator FadeIn uses a yield return 0; line in its while loop so that it updates at the same rate as update (every frame). Yield return 0 basically tells it to wait a frame.

We created a variable of type AnimationCurve, which gives us access to a curve we can manipulate by changing its shape or adding/removing points to control how a value fluctuates. We used this to control the FadeIn IEnumerator. We then duplicated this IEnumerator to create a FadeOut version as well (just swapped the values in the while loop to run the other way to make the rest of the code consistent). FadeOut was then added to a public method, FadeTo. The both receive a string variable that corresponds to the scene name of what scene they should be fading to.

We then just went to all of the scripts/menus where we move between scenes and added this FadeTo call from the SceneFader. This included the pause menu, game over menu, and main menu. This also included making sure to drag our SceneFader into the reference for all of these scripts since they did not want to use FindGameobjectOfType for computer processing reasons.

My thoughts on why an IEnumerator was used here is that they seem to be good with dealing with something you want to happen over time, and they can run while other actions are running/processing. Since we just wanted a fade effect, it’s helpful to let everything else continue to run as opposed to interrupting something to finish this effect. The time element basically lets us have a pseudo”Update” method that only runs for a certain amount of time and then never needs to check again.

SUMMARY

  • If you want a UI element to cover everything (including other UI elements) make sure to check the Sorting Order
  • I still need to look into IEnumerators to get a better grasp on their specific uses

Tower Defense Tutorial – Brackeys – Ep. 23

March 2, 2019

Tower Defense Tutorial

Episode 23 – Enemy Health Bars

Youtube – How to make a Tower Defense Game (E23 HEALTH BARS) – Unity Tutorial

By: Brackeys
Ep. 23

In this tutorial we created health bars for the enemies.

We began by creating the foundation for the UI asset. We created a new World Space canvas, added a child UI Image object as our health background, then childed a UI image to that that would be our actual health bar. The BG was given a transparent black color, while the health bar was a fully opaque light green.

We then childed this full group of UI assets to our Enemy prefab. The position needed fixed when this was applied, and the scaling reset so I had to reset that manually as well. This created a health bar that would follow our enemies now. We would need a bit of a tracking script if our enemies rotated (so the health bar would not), but currently the enemies don’t rotate at all so this is not necessary.

To make our health bar actually do something, we started by dragging in a white square image to the source image of the health bar UI image, which was created for the tutorial. It was just a simple 2 x 2 white square. We then changed the Image Type to Filled, and selected the Fill Method “Horizontal”. This allows us to control how much of the image is “filled” horizontally, between 0 and 1 (0 – 100%). This has a very similar effect to what I usually script for health bars which is just a scale multiplier between 1 and 0 tied to the x scale of an object with the anchor point located all the way on the left/right. Either way, this still needs to be tied into health scripts.

Our fill amount for this health bar image needs to be between 0 and 1, so we need to represent our current enemy health as some fraction of our enemy max health. This is easy enough to do by simply holding a value for the max health and dividing the current health by the max health.

PROBLEMS

Bug

I found a bug where some of the turrets I was placing could not be upgraded. They were base turrets but when I selected them it already said they were “Maxed Out” and I could not upgrade them. It was only a select few turrets, and I realized they were in locations where I had an upgraded turret previously and sold it to make room for a new turret.

I believe this bug is simply caused by the fact that the state of upgraded is tied to the node location, so when we upgrade and then sell, the upgrade state is not being reset. That should be a simple fix of resetting the upgrade state when the Sell method is invoked.

Solved

This appeared to be the case as the bug hasn’t come back since I simply added a line to set the isUpgraded bool to false in the Sell method of the Node script.

SUMMARY

  • Another way to create health bars: under the Image (script) component; select image type Filled, and choose Fill Method “Horizontal”

Tower Defense Tutorial – Brackeys – Ep. 22

March 1, 2019

Tower Defense Tutorial

Episode 22 – Main Menu

Youtube – How to make a Tower Defense Game (E22 MAIN MENU) – Unity Tutorial

By: Brackeys
Ep. 22

In this tutorial we created the Main Menu scene for the game.

We duplicated the original game scene to start, and deleted out everything except the Light, Main Camera, and Environment. Then we only kept the Ground Plane from the environment. We then added a Standard Turret Prefab to be a central object for our menu.

We then edited the sky box to something other than the Unity default. We selected Solid Color for it, and used the color picker to pick the top most color of our ground plane so the sky matched this very final gradient of color. This made it seem like the background was one solid, endless color gradient for the most part.

We then created a World Space canvas with text fitted to it for our PLAY text. We placed this on top of the turret prefab in our menu. We then wanted to make this text clickable, so we just added a Button (script) component. This basically turned the text into a button for us. We could even add our previous animation by simply adding an Animator component and selected our Button Controller for the Controller.

We then created the MainMenu script which will hold the main functionality of this scene. This started by creating public Play and Quit methods for our Play Button and Quit Button. Quit was just Application.Quit, and Play loaded our MainLevel scene.

Finally, we added a bit of animation to our Main Menu to utilize the fact it is set in a 3D environment. We added the two button canvases as children to the PartToRotate object of the turret, and created a quick animation for that that just rotated the entire turret and UI element back and forth a bit over time. This really made the menu feel alive and 3D.

SUMMARY

  • To set current editor view as camera view: select camera and press: Ctrl + Shift + F
  • Set skybox to solid color and use color picker to select farthest/top most color of ground plane for a quick/easy way to make ground and sky look like one coherent background
  • When referencing scene names, make a string and set its value to that scene name so if at any point you want to change the scene name, you just change that string variable’s value and it will fix it in all locations needed

Tower Defense Tutorial – Brackeys – Ep. 21

February 28, 2019

Tower Defense Tutorial

Episode 21 – Pause Menu

Youtube – How to make a Tower Defense Game (E21 PAUSE MENU) – Unity Tutorial

By: Brackeys
Ep. 21

This tutorial focused on creating the Pause Menu.

To start, we create another UI Panel as the base for the pause menu, and added buttons for: Continue, Retry and Menu. This also had text saying “Paused”.

We created a new script on our Game Manager, PauseMenu. This would deal with the functionality of activating/deactivating our pause menu UI elements. This was done with a method called Toggle, which used a command of ui.SetActive(!ui.activeSelf) which would set whether it was enabled or not to the opposite of what it currently is.

We then got to actually pausing the game. This can be done by simply setting Time.timeScale = 0f. It is commonly mistaken that you also need to set Time.fixedDeltaTime to 0 as well, but this is actually taken care of by Time.timeScale already. We also need to unpause, so we set Time.timeScale back to 1f when that is needed.

It is important to note that while Time.timeScale is at 0, this does prevent some things from working. The hover color of UI buttons was still fine as it is not affected by the timescale, but animations you are running with the Animator will be. They need a specific setting changed in order to function properly. This was shown by trying to fade in our pause menu. Initially, we created a simple recorded animation of changing the alpha from 0 to 1, but when we ran it in game it did not appear. That is because the animation was frozen with the timeScale.

To prevent the animation from being affected by our timescale variation, we change the “Update Mode” in the Animator component of the object we are animating from Normal to Unscaled Time.

Then, we also wanted to animate the buttons some (instead of just having a simple highlight color). To start, we went to the Button (script) component and changed the Transition to Animation. We then selected AutoGenerate Animation. This gave us 4 options in the Animation tab for: Normal, Highlighted, Pressed, Disabled. These are the 4 states of the button. These let you set an animation to start whenever these separate events occur.

SUMMARY

  • Use [gameObject].SetActive(![gameObject].activeSelf) to inverse the current enabled state of a gameObject
  • Use Time.timeScale = 0f; to do a simple pause of your game. This should also set Time.fixedDeltaTime to 0f behind the scenes so you do not need to set this as well. (To unpause, set Time.timeScale back to 1f.)
  • If you want to animate objects during timescale = 0 (like pause menu animations), make sure to change their Animator component Update Modes from Normal to Unscaled Time.
  • To animate UI buttons, select Animation for Transition under the Button (script) component (built into Unity UI buttons). Can then select AutoGenerate animation to record animations like anything else, and for all 4 different states of the button (Normal, Highlighted, Pressed, Disabled).

Tower Defense Tutorial – Brackeys – Ep. 20

February 24, 2019

Tower Defense Tutorial

Episode 20 – Sell

Youtube – How to make a Tower Defense Game (E20 SELL) – Unity Tutorial

By: Brackeys
Ep. 20

This tutorial focuses on implementing the “sell” functionality to go along with the sell UI button we have. We are also going to setup an upgraded version of the missile launcher and the laser beamer turret.

The upgraded versions of the missile launcher and laser beamer turret were just upscaled versions with some buffed stats and different material colors. These were set in the Shop TurretBluePrint editor sections as well.

For the selling function, we wanted to add that to our Node script. However, since we just wanted to code something standard to create the sell value of a turret, we ended up going to the TurretBluePrint to create this calculated sell value. This was done because we can now just reference the TurretBluePrint class anytime we want the sell amount, and if we ever want to change how that is calculated, we can just change it in one place instead of looking around for everywhere it is used. In TurretBluePrint class, we simply added a method, GetSellAmount, that returns an int that is just the cost divided by 2 for now. This method can now be referenced in the Node script to get that sell value.

The UI system is very easy to add functionality to. The main UI object holds the central script that keeps track of what we have selected and call methods on that node specifically, as well as containing all the basic UI methods (such as on click events). It’s very easy to know that anything dealing with altering a node goes through this script. It also keeps a lot of our UI functionality organized in one location.

SUMMARY

  • If you are using a variable multiple times that needs calculated, but may want to alter this calculation throughout the design process, it is good to have this done in one location as a small helper method and then reference this method when you want that value. That way you only have to change the calculations in one place to change them globally.

Tower Defense Tutorial – Brackeys – Ep. 19

February 23, 2019

Tower Defense Tutorial

Episode 19 – Upgrade

Youtube – How to make a Tower Defense Game (E19 UPGRADE) – Unity Tutorial

By: Brackeys
Ep. 19

This tutorial goes over upgrading our turrets after selecting them.

We started by moving the BuildTurretOn method from the BuildManager script to the Node script, and renamed it BuildTurret (since it will be obvious it is “on” that node now anyway). This was done because BuildTurretOn was making a lot of references to the Node script anyway, so it made more sense to just handle everything locally to reduce the number of references needed.

Next we created the UpgradeTurret method. This was mostly a copy/paste of our BuildTurret method, with a few tweaks (having a separate cost, possibly a separate effect). The biggest difference was that we couldn’t just instantiate the upgraded turret since we already have one there; we need to remove the initial turret first.

We created a new prefab for the upgraded version of our standard turret. We duplicated the original, scaled that up some, and changed one of the material colors just to make it clear it was a different version. I liked the way they organized this in the Asset hierarchy. Our folder structure was already: Imports -> Models -> [Model Name]. We further branched this into two separate folders to hold the materials for the standard turret and a folder for the materials of the upgraded turret.

We edited the NodeUI so that the upgrade cost is tied to the currently selected turret’s TurretBluePrint now. This makes sure the upgrade cost updates according to which type of turret is selected.

Finally, we created the case for when the turret has no more upgrades available. In the NodeUI script, we check the upgrade state (currently just isUpgraded) on the turret. If it is not in the final state, perform normal upgrade functions, if it is, set the text to something like “Done” or “Maxed Out”, and set the upgrade button itself it be non-interactible (upgradeButton.interactable = false).

SUMMARY

  • If a method makes a lot of references to another script/class, it might make more sense to just move that method into the script/class
  • They use an underscore ( _ ) before a variable to indicate it is just a local variable field version of a variable (i.e. _turret instead of turret since _turret is created and used specifically within a single, smaller method)
  • If you have upgraded versions of models that are mostly varying the materials, create separate Material folders for each variation to keep organized
  • Use buttonName.interactible = false to stop button from having hovering animations or performing actions when pressed