Emil S.D

Personal blog & portfolio

Learning Unity: 2D Tower Defense Game

Learning Unity: 2D Tower Defense Game

November 9, 2023
Emil S. D

Project: ESD2D-TowerDefense

Tutorial followed:


Step 1: Laying the Foundation with Map, Enemy, and Pathway Creation

To kick things off, I focused on the basics. I constructed a grid-based map which would serve as the playing field. Then I removed certain grid cells to carve out a path—an essential track for the enemy characters to follow. It's pretty manual for now, but I'm thinking of eventually coding an algorithm to auto-generate these paths, making each map unique.
Next, I placed markers along the path to guide the enemies. I used yellow diamond icons for these navigational points. For a clear start and end to the pathway, I marked the beginning with a green icon and the end with a red one.
notion image
To streamline my development work, I converted the 'cells'—or 'plots,' as the tutorial refers to them—into prefabs. I did the same for the enemy, which in my project is represented by a circle. Prefabs are a huge time-saver; make a change to one, and it automatically updates all instances. From what I understand, it's a standard technique in game development.
I created a central script to manage the game, aptly named LevelManager. This script is designed as a static object, ensuring it's not tied to any specific instance within the game. This way, the LevelManager can be easily accessed from other scripts to control the game's flow.
Here's the simple code snippet for the LevelManager:
public class LevelManager : MonoBehaviour { // Static instance of the LevelManager that can be accessed from anywhere public static LevelManager main; // Public Transform to hold the starting point of the path public Transform startPoint; // Array to hold the sequence of path points public Transform[] path; private void Awake() { // Assigns this script instance to the static instance upon the object's awakening main = this; } }
Following the setup of the map and pathway, I crafted an EnemyMovement script to dictate how the enemy characters move. The script ensures that the enemy follows the path laid out by the waypoints, and upon reaching the end of the path, the enemy object is programmed to self-destruct.
Here's the refined EnemyMovement script:
public class EnemyMovement : MonoBehaviour { // Reference to the Rigidbody2D component for physics-based movement [Header("References")] [SerializeField] private Rigidbody2D rb; // Attribute to control the enemy's movement speed [Header("Attributes")] [SerializeField] private float moveSpeed = 2f; // The current target point the enemy is moving towards private Transform target; // Index to track which point in the path array the enemy is targeting private int pathIndex = 0; // Start is called before the first frame update private void Start() { // Initialize the target as the first point in the LevelManager's path array target = LevelManager.main.path[pathIndex]; } // Update is called once per frame private void Update() { // If the enemy is within a small distance of the target point if (Vector2.Distance(target.position, transform.position) <= 0.1f) { // Move to the next point pathIndex++; // If we've reached the end of the path if (pathIndex == LevelManager.main.path.Length) { // Destroy the enemy game object Destroy(gameObject); return; } else { // Update the target to the next point in the path target = LevelManager.main.path[pathIndex]; } } } // FixedUpdate is called at a fixed time interval and is used for physics updates private void FixedUpdate() { // Calculate the direction vector towards the target point Vector2 direction = (target.position - transform.position).normalized; // Apply the movement in the direction of the target with the set speed rb.velocity = direction * moveSpeed; } }
Here is a demo: