Tower Defense Tutorial – Brackeys – Ep. 17

February 17, 2019

Tower Defense Tutorial

Episode 17 – Game Over

Youtube – How to make a Tower Defense Game (E17 GAME OVER) – Unity Tutorial

By: Brackeys
Ep. 17

This tutorial deals with creating the Game Over screen as a series of UI elements.

We started by adding a gameObject to our OveralyCanvas titled GameOver. This gameobject will hold all of the UI elements dealing with the game over state: new panel, text objects, and buttons for retry and menu.

We changed the OverlayCanvas scaling to “Scale with Screen Size” and used the slider to dictate that it would go by the height of the screen to scale our overlay UI canvas.

For scripting the game over scenario, we decided to expose the gameEnded bool variable to make it easier for everything to know when the game was over. This is useful for basic things such as disabling game inputs on the game over screen. We exposed it by making it a public static bool (and also renaming it to GameIsOver).

Making GameIsOver a public static variable however means it carries over from scene to scene, retaining its value, so we need a way to reset this value. This is easily solved by setting the value of GameIsOver to false in the Start method of our GameManager, as the Start method is called every time a scene begins.

To better organize our objects and scripts, the GameOver game object containing all the game over UI objects also holds the GameOver script. This script will handle everything during the GameOver phase of the game. This works by having the entire GameOver object disabled, and then the GameManager enables it when the GameOver state is reached. At this point, the GameOver object has an OnEnable method in its script, which acts like Start, but occurs when the object is enabled. This begins all the processes needed to be handled during the GameOver phase.

Finally, we wanted to add some animations to our game over screen. We used a basic approach to fading the UI objects in, with some minimal movement and scaling of text/buttons. There was a suggested easy way to fade in UI objects. If you add a “Canvas Group” component to a UI element, it has an alpha value directly tied to it that effects that entire object. This makes it very easy to fade objects in/out by just varying this value from 0 – 1.

SUMMARY

  • Have your GameIsOver as a static bool to make it easier for every script to access this to basically shut down during the game over state
  • Group your Game Over scripting into a single objects that starts OnEnable to keep things organized with minimal references needed
  • Use Canvas Group components on UI elements to easily change entire alpha value (good for fade animations)
  • Offsetting your UI animations can make the screen feel more organic/less robotic

Tower Defense Tutorial – Brackeys – Ep. 16

February 16, 2019

Tower Defense Tutorial

Episode 16 – Slowing

Youtube – How to make a Tower Defense Game (E16 SLOWING) – Unity Tutorial

By: Brackeys
Ep. 16

This tutorial will clean up some of the Turret coding, as well as add a slowing effect to the Laser Beamer turret, as well as damage over time (DoT).

We added this line of code to apply the damage over time to enemies:

targetEnemy.TakeDamage(damageOverTime * Time.deltaTime);

This initially held the GetComponent() call to get the Enemy script component of the target, but this would be very expensive to do every frame. To remedy this, we created the targetEnemy variable which is assigned the GetComponent() value when we select a new target, so it only needs done once each time the laser starts hitting a target.

To clean up our Enemy script coding, we separated it out into two scripts: Enemy and Enemy Movement. Brackeys suggests it is a good practice to keep all of your enemy’s stats or values that you want to change about them in one script, and have the other script components reach out to that information when they need those values (i.e. speed, health, etc.).

To connect our new EnemyMovement script to the original Enemy script, we simply added an Enemy variable, enemy, and then GetComponent() on that at start. To further ensure they are connected (i.e. Future editors know to keep these together), we added a RequireComponent(typeof(Enemy)) above the class name.

We wanted the laser to slow the object a consistent amount. We did not want slows to stack from multiple lasers or increase over time in any way. This resulted in creating a startSpeed to go along with speed. Speed was set equal to startSpeed in the Start method of Enemy. This allows us to constantly set speed as a fraction of startSpeed, since startSpeed is never modified. This also meant we didn’t want to show speed in the inspector, but still needed to keep it public, so we added [HideInInspector] above it so it did not show.

This worked well to slow the enemy, but then it remained slow forever. We needed to reset the speed somehow. Their solution was to just reset the speed every frame in the Update that was moving the enemy (after the movement occurred). While this works, this seems like a lot of extra calculations that could be solved in a cleaner way.

Suggested cleaner solution to slow and movement being off by a frame: Have a list of debuffs that the enemy script goes through each frame to check what debuffs are currently on it, and then apply those to any actions it does.

In this case, we actually went into the Script Execution Order (Project Settings -> Script Execution Order). This allows you to drag in scripts to dictate what order they are processed in. The number value entered is the number of milliseconds between this script and the default time.

SUMMARY

  • Simplest way to do damage over time is to have a method dealing damage * time.deltaTime that is called in Update somehow
  • RequireComponent makes sure that any time you add this script to an object, it will also add the specified component as well. Good for making sure all the components needed for a certain script to reference are on a given object.
  • It is good practice to keep all of an object’s “stats” in one place, and have other functionality that references these stats separated out into other components/scripts. (i.e. Our enemy stats were kept in Enemy, but another script, EnemyMovement, was created which referenced Enemy for stats like speed and then applied that to all the functionality internally)
  • Use [HideInInspector] if you want a public variable but don’t want it shown in the inspector
  • You can use the Script Execution Order to dictate what order scripts are run

Tower Defense Tutorial – Brackeys – Ep. 15

February 15, 2019

Tower Defense Tutorial

Episode 15 – Laser Beamer

Youtube – How to make a Tower Defense Game (E15 LASER EFFECTS) – Unity Tutorial

By: Brackeys
Ep. 15

This tutorial will focus on creating extra effects for our laser. We’re adding a LaserImpact particle system, starting as a duplicate of the BulletImpact particles.

We started by making it a new material, LaserImpact material, and making this green with some emission. As many other particle effect parameters, this is setup differently in newer versions of unity. The intensity is in the color selector palette after turning on “Emission” for the material. Since we have so many particle systems now, we’re narrowing down what they collide with. We put all the nodes and ground planes on an “Environment” layer and made sure the particle system only collided with that.

Instead of making this particle effect its own prefab like the others, we attached it as a child to the Laser Beamer object. This would then just be an object we enable/disable when needed. For the particle system, we actually use Play() and Stop(), instead of enable/disable. This makes sure you aren’t creating multiple instances of the particle effect, and also makes it so that when you turn off the particle system, it doesn’t immediately go away. The residual particles will still do their thing.

To position the particle system, we just started by making its position that of the target. This however puts it directly in the middle of the target, where we would prefer having it on the surface where the object is hit. To do this, we created a vector that is the difference between our turret’s firepoint and the target to get the direction. Then we rotated the particle system to match this direction, and added/subtracted a small amount from the target position to place it slightly closer to our turret (so hopefully closer to the surface of the object). There might be a cleaner and more consistent way to do this with rays.

We wanted to add more effects to this laser, so we added a child particle system to this original laser ImpactEffect. Play()/Stop() will also apply to any children particle systems of an object. The material they used for this wanted to use the shader Particles -> Additive, which is only a Legacy option now. The new Particles -> Standard Surface shader has a rendering mode blending option that has an additive option, so I tried to see if that was similar. It seemed to give a similar effect, as long as I put the material (we were using the default particle material) in the Albedo map.

We gave the particle a blinking effect by editing the “Color Over Lifetime” to have 0 alpha at the end. So as it would loop, it basically faded in and out very quickly. Finally we added a green light to this particle system as an extra glowing effect. This however, would leave the light at its last position when an object got out of range.

When we went to fix the light (enable/disable it), they mention we could use animations instead to control all of these particle system events as opposed to scripting all of them. The light was just another reference in the Turret script that we enabled/disabled with all the other laser effects.

SUMMARY

  • I really need to look into tutorials for the new particle system editor to help find equivalent options for these older tutorials
  • Use Play(), Stop() with particle effects instead of enable = true or false for normal use
  • Create blinking effect in particle system with looping, short lifetime, and setting “Color over lifetime” final alpha value to 0

Tower Defense Tutorial – Brackeys – Ep. 14

February 13, 2019

Tower Defense Tutorial

Episode 14 – Laser Beamer

Youtube – How to make a Tower Defense Game (E14 LASER BEAMER) – Unity Tutorial

By: Brackeys
Ep. 14

This tutorial creates the Laser Beamer, yes beamer, object prefab. Something I’ve done when importing these to make it more similar to the tutorial, under the Materials tab for this imported model, I use “Extract Materials” to make sure all of the materials become easily available to alter and move around in the Unity editor. Before making it into a prefab, we did the same steps we did with the other turrets: add partToRotate empty object, add firePoint empty object, child turret head and firepoint to partToRotate empty so they rotate properly/easily with a forward facing z-axis object.

Everything else was also updated similarly to the other turrets. We added another TurretBluePrint public class to the Shop script so we can inform it of the new prefab to use for the LaserBeamer and its cost. We then added the LaserBeamer shop button (sprite image on UI) and added its new click event for selecting the LaserBeamer.

The laser beamer is different in that its projectile will use a Line Renderer component to simulate a laster. This has clearly received a lot of updates over the several iterations of Unity between now and this tutorial. The “Positions” section has more of a table setup. The “Width” parameter section is now actually a small line graph instead of just values (assuming this allows for more variation with curves, etc.).

The line renderer material gave me some issues, which I cover in PROBLEMS below. However, it seems the material I chose doesn’t allow for variation of the alpha value in the line renderer color component. Another difference here is the suggested shader for the line renderer material was “Particles – Alpha Blended”, which no longer exists. I used “Particles – Standard Unlit” which worked for me. The colors are also different now. Instead of just a start and end color option, it is now a full gradient preview bar with colors on the bottom and alpha values on the top.

Then we edited the Turret script to deal with this new type of weapon. We separated out the variable headers from Attributes into General, Use Bullets (default), and Use Laser to keep everything organized. Then we moved on to dealing with the line renderer in a method, Laser.

We started scripting the line renderer by setting its positions (values in its position array that determine the points to connect with a line). Since we only have two points, those are the start and end point of our line. It’s as easy as:

lineRenderer.SetPosition(0, firePoint.position);
lineRenderer.SetPosition(1, target.position);

Where the first input in SetPosition is the element number in the position array of the line renderer, and the second input is what that position is. So this example draws a line between our firePoint (shooting location) and whatever the target is.

Our laser worked, but it would stay in its last position if the target moved out of range (since it no longer needed to update its location). Since we already had a return happening for the check when there is no target, we just added a laser specific check to also enable = false for the line renderer when there is no target.

PROBLEM

SOLVED: My line renderer was not displaying properly after applying a basic material to it in the prefab editor (it was just solid black, when the material was white). At first I thought this was a lighting issue in the new prefab editor, so I found out that you can create a scene to use as the prefab editor scene and add it in your Project Settings. So I did that and it was still black, but I noticed if I rotate around it was white for about 180 degrees of viewing rotation. I then noticed the next part of the tutorial mentioned changing the shader for the material, and this directly solved the issue. Line renderers might deal with materials strangely, and may often use non-default shaders.

BONUS OBJECTIVES

Add particle effect to the end of the laser line renderer for that sparking impact effect a lot of lasers have.

To set up the Turret variables/editor even better, have a variable called UseBullets, or an enumerator to select either Bullets or Laser, then show fields depending on what you selected. Create an editor script for this. Look up “Unity Custom Editor”.

SUMMARY

  • When importing models, use “Extract Materials” to specifically pull out all of the materials to make them easier to edit.
  • Check the shader for the material you apply to line renderers since they seem to act uniquely
  • Look into “Unity Custom Editor” to learn about editor scripts

Tower Defense Tutorial – Brackeys – Ep. 13

February 13, 2019

Tower Defense Tutorial

Episode 13 – Lives

Youtube – How to make a Tower Defense Game (E13 LIVES) – Unity Tutorial

By: Brackeys
Ep. 13

We started by adding another public int, Lives, to the playerstats script. We then copied the bottom in-game canvas and pasted it to the top to hold our lives UI text element.

This tutorial involves a lot of references between different scripts. They suggest that if you’re making a larger game with a lot of moving components that you want to optimize, make calls to methods within the other scripts that do the changes locally, as opposed to directly altering the variables from the other script. In this tutorial, they end up just having everything go through the GameManager and having it handle everything locally.

We created a GameManager script for the gameManager object. The first thing we have this doing is handling the game over situation. It checks if lives <= 0, and if so, runs the EndGame method. We also added the standard gameEnded bool just so the check doesn’t run the EndGame method many times.

We then looked at the enemy script to start fleshing out its functionality. We added a health int, as well as methods to deal with receiving damage, TakeDamage, and dying, Die. TakeDamage also receives an int as input to determine how much damage to apply.

Next was filling out the Bullet script. We updated the Damage method so it grabs the Enemy script component of what it hits now and calls the TakeDamage method we added. We also added a damage int to Bullet that we could pass into TakeDamage to control how much health Damage removes.

Finally, we created another particle effect for the death of the enemy objects. This was another simple one copied from our bullet impact effect, we just varied the values a bit and changed the material to that of the enemy to look like the enemy is breaking apart. I also noted some differences in the particle editor over the large difference in Unity versions.

LOCATIONS OF BASIC METHODS

This section will just list some of the small basic methods created, where they are placed, whether they are public/private/etc., and whether they take input variables to help keep track of a framework for creating really simple games.

      Enemy

    • Take Damage(int amount) – Public – Applies damage to the object based on the int input
    • Die() – Private – Performs basic functions when health reaches 0, like destroy gameObject
      Game Manager

    • End Game – Private – performs actions when end game state is reached (i.e. Lives are 0)
      Bullet

    • Damage(Transform enemy) – private – gets the Enemy script component of the transform entered and calls the TakeDamage method, sending with it the damage variable from Bullet

SUMMARY

  • Larger projects may work better by calling internal methods of separate scripts to handle variables locally instead of directly changing the variables from the outside script
  • Make small, separate methods to deal with “EndPaths”. Could look into this terminology more.
  • Unity’s particle creation system has definitely changed over time, so just be aware when doing older tutorials.

Tower Defense Tutorial – Brackeys – Ep. 12

February 12 2019

Tower Defense Tutorial

Episode 12 – User Interface

Youtube – How to make a Tower Defense Game (E12 USER INTERFACE) – Unity Tutorial

By: Brackeys
Ep. 12

We created another bool property in BuildManager called HasMoney, which checks if the playerstats has enough money to build what the player is trying to build. This was then used as a check to determine what color a node should be when the player hovers over it.

Next we moved on to creating UI. We moved the timer and money into a canvas in world space, below the main play area. There are weird interactions between UI element scaling and font size. They multiply together so you can get the same size by raising one and lowering the other, but even though the give the same multiplicative size, the resolution can be different.

We updated the wave spawner timer. We added a clamp to it so it never goes below 0. We also edited the formatting of the countdown timer text so that it showed 2 digits before the decimal point and 2 after (the hundredths place). This was done with string.Format(“{0:00.00}”, countdown).

We also added a script, MoneyUI, to the money UI element. This solely references the playerstats money variable and updates to that as text. This definitely does not need to be done in Update, and would be more efficient to happen when the money value changes only.

We added cost UI elements to the turret buttons. These were just simple panel and text UI elements, with the cost hard coded (hard typed) in. You could add functionality to tie this to their true values in script.

Finally we added some particle effects on building a turret. This started by creating an empty game object slightly raised vertically, then adding the particle system as a child to this. This was with the intention of rotating the parent empty object without moving the anchor of the particle system.

PROBLEMS

My UI elements were acting strange between the Horizontal Layout Group on the Canvas and the Layout Elements on the UI buttons (turret images). I was not getting the expected results with the preferred height and width of the Layout Elements (they would not change to those values even though they had room), but I could just manually change them just fine (so the horizontal layout group wasn’t restricting them from being those values). This is extra strange as there was an Editor note specifically stating “Some Values driven by HorizontalLayoutGroup”.

SUMMARY

  • Scaling UI Element to fit that around it: Under anchor presets, hold “Alt” and select the bottom right corner option
  • Font size multiplies with the UI element scaling, and you can get weird results sometimes. i.e. I had to change my UI scaling down from 1 to 0.1 because even though I could just use one tenth the font size to fit the same space, this gave the text poor resolution.
  • Use string.Format to determine number of decimal places to show in number strings. The amount before the decimal point appears to also be important. (i.e. We used 0:00.00, which indicated which element to have two digits before and after the decimal point)

Tower Defense Tutorial – Brackeys – Ep. 11

February 4, 2019

Tower Defense Tutorial

Episode 11 – Currency

Youtube – How to make a Tower Defense Game (E11 CURRENCY) – Unity Tutorial

By: Brackeys
Ep. 11

This episode gets into setting up the currency system for the game. We started by creating the TurretBluePrint script. This was set as System.Serializable, which lets us see the fields of the script in the editor. We also removed the MonoBehaviour reference (very important, I initially missed this and it was not showing up in the editor properly). We then went back through previous scripts (such as BuildManager and Node) and applied this new TurretBluePrint class where it made sense.

We finally moved the method that actually builds the turrets from the Node script into the BuildManager script. This started by creating a bool property CanBuild in the BuildManager. As a property, we only allow it to “get” something (it only has the get part of get/set). So it was:
Public bool CanBuild {get {return turretToBuild != null}}
Similar to writing a small function that checks if turretToBuild is equal to null or not.

We created a small helper method in the Node script simply titled GetBuildPosition. This returned a vector3 that summed the node’s transform.position and the determined positionOffset. This vector3 could then directly be referenced as the precise location to instantiate a turret relative to the node selected. Also wanted to make the GameObject turret variable in node public, so we added a Header “Optional” to make it very clear in the editor it was ok if this was not filled with something.

This is how everything works now:

  • Start by clicking on shop icon
  • Performs Shop method tied to button: calls SelectTurretToBuild method from BuildManager and sends it TurretBluePrint (class holding a turret prefab and a cost int) pertaining to the specific turret selected
  • In BuildManager, this method just sets the turretToBuild TurretBluePrint variable to the passed in TurretBluePrint
  • Then when player clicks on a node (OnMouseDown), it performs a few checks that just return first: is it over a UI element, if BuildManager’s CanBuild is false, or if turret does not equal null
  • If it passes all these checks, it calls the BuildTurretOn method from the BuildManager and passes in itself as the Node input for the method
  • BuildTurretOn instantiates the GameObject portion of the turretToBuild TurretBluePrint class (turretToBuild.prefab) at the proper position (from the node helper method GetBuildPosition)
  • Finally, BuildTurretOn also sets that node.turret variable to the instantiated turret gameObject (that node’s turret variable will no longer be null, so it will not pass the first OnMouseDown check)

Now we start on dealing with actual currency. We created a script PlayerStats to add to the GameManager to hold onto any player related stats. The most direct one being Money, which was created as a public static int so we could access it from anywhere easily. It will also carry over from one scene to the next. We then edited the BuildTurretOn method in the BuildManager so it would properly deal with currency. It first checks if the player has enough money before placing a turret (if they do not, then it does not do anything else). If that passes, it creates the turret and subtracts the cost from the player’s current money.

SUMMARY

  • *** Very Helpful! By removing the MonoBehaviour reference and adding the System.Serializable to a class, we can use it as a type of container to simply store multiple variables (different types and values) with multiple shown in the editor. For example, our TurretBluePrint class held a public GameObject and public int, so anytime we referenced a public TurretBluePrint in a script, it created a slot for a GameObject and an int in the editor tied to this one variable
  • Use Boolean properties (just “get” variables) as a safe and effective way to check state of other variables
  • Use small helper functions for cases of small arithmetic functions that will probably be needed a lot, especially if they can be well defined so the reason for the math is clear
  • Be careful with public static variables as they persist over scenes

Tower Defense Tutorial – Brackeys – Ep. 10

February 3, 2019

Tower Defense Tutorial

Episode 10 – Missile

Youtube – How to make a Tower Defense Game (E10 MISSILES) – Unity Tutorial

By: Brackeys
Ep. 10

This tutorial focused on the missile prefabs for the missile launcher object. There was a heavy focus on effects and visuals, but there were still some additional gameplay elements added to the Bullet scripts of the missiles specifically.

For the interesting gameplay of the missiles, a Physics.OverlapSphere was added so they could find other nearby gameObjects within a determined explosionRadius and damage those objects as well. This OverlapSphere puts all the colliders it finds into an array, which is then dealt with by a foreach loop.

We created a new particle effect for the missile. I still don’t quite understand the new nested prefab QoL changes in Unity, but I did create a nested prefab for this effect. The main effect was the debris falling apart, similar to the bullet. The child effect were flames, which were orange cubes that floated up. Finally we also added a point light that very quickly fades out. The fade out was done with the Animation window by recording and simply starting with the desired initial intensity, then reducing the intensity to 0 at a later time stamp.

SUMMARY

  • If you have a visual model that isn’t on the axes you want for any reason, just call it “Graphics” or “GFX”, and put it as a child to what you will consider the true gameObject to interact with and align that properly by rotating the new GFX/Graphics element
  • Look into particle effects, there are a lot of options
  • Look into nested prefabs in Unity 2018.3+
  • Physics.Overlap sphere is useful to find collidable gameObjects around a location

Tower Defense Tutorial – Brackeys – Ep. 09

January 29, 2019

Tower Defense Tutorial

Episode 09 – Missile Launcher

Youtube – How to make a Tower Defense Game (E09 MISSILE LAUNCHER) – Unity Tutorial

By: Brackeys
Ep. 09

This tutorial covers making the Missile Launcher turret. A lot of it is the same as setting up the first turret, but it’s good practice to repeat the setup. It is extra useful for me because I am using Unity 2018.3 and there is a new way of working with prefabs so any practice with that is very useful.

There is a keyboard shortcut for selecting a variable and changing its name across all instances within the script (and even other scripts). Use Ctrl + r + r, then just type the new name over the old one.

SUMMARY

  • VS Keyboard Shortcut: Ctrl + r + r : Lets you replace all instances of a variable (even across scripts) with a new name
  • Just keep practicing with new Unity prefab setup
  • Simple way of creating UI icon from last time worked well again here

Tower Defense Tutorial – Brackeys – Ep. 08

January 27, 2019

Tower Defense Tutorial

Episode 08 – Shop

Youtube – How to make a Tower Defense Game (E08 SHOP) – Unity Tutorial

By: Brackeys
Ep. 08

This tutorial begins to set up the shop UI for the tower defense game. Setting up the shop UI begins with adding a UI Panel to the Canvas. This was brought down to the bottom and set to stretch across horizontally with the anchors. Then a Horizontal Layout Group component was added, which helps deal with the organization/alignment of children UI objects within this UI object’s space. Those children UI objects are buttons, which are used to choose different turret options for purchase. Going along with the Horizontal Layout Group, all of the buttons had a Layout Element component added to them. This allows you to enter some information on things such as preferred dimension, min dimensions, etc.

We used a quick and simple method to create a nice visual “button” so the player knows what tower is being selected to build. We went into the existing turret model’s prefab and took a screen shot of it with the Snip tool. Then we took that over to Photoshop and erased out the background (this was more easily done by making sure to turn off the skybox in the prefab editor visual so the background was entirely the single Unity blue color). I also changed the PS canvas size to a nice 256 x 256 pixels. Then exported out a .PNG with transparency on. We pulled the image into the Unity editor and changed the texture to a 2D sprite. This image could then be used as the UI sprite of the button, and we had a button that is a sample image of the actual model of our turret.

A Shop script was added to the Shop gameObject. This mostly deals with the actions that the buttons on the UI should perform. This deals a lot with relaying information to the BuildManager script, so a reference to that is immediately set in the Start of the Shop script. It then has methods dictating what turret the BuildManager should be preparing to build. Then, as seen in the earlier tutorials, the Nodes (spaces to place turrets) have their own scripts to access the BuildManager to see what is prepared to be built, and then the Node script actually instantiates the turret as long as the proper conditions are met. The BuildManager acts as the central scripting “hub” for dealing with all of the turret building.

As a final QoL touch for the game, a restriction was placed for highlighting and selecting nodes that were behind important interactive UI elements (we don’t want players placing turrets when they are simply going to select a turret to build). To do this, we went into the Node script and added the namespace {using UnityEngine.EventSystems;}. Then in both the OnMouseDown and OnMouseEnter methods, we added an if statement that just returns {if (EventSystem.current.IsPointerOverGameObject())}. This stops the rest of the method from occurring if the mouse cursor is already on an EventSystems object (i.e. a UI element).

SUMMARY

  • Use Horizontal Group Layout and Layout Elements components on UI elements to help organize and space them nicely
  • Create simple UI button sprite images of models with Snip of prefab editor image, Photoshop out background color, export as .PNG with transparency
  • Have a script that deals with the UI element methods (i.e. what the buttons do) and have it reference the script(s) where most of the “work” is done
  • Use an if statement check with UnityEngine.EventSystems to make sure players clicking on UI elements don’t click on other game elements with that same click, using IsPointerOverGameObject