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