Implementing Shielded Enemies in Unity

Damian Dąbrowski
3 min readMar 5, 2024

--

Adding variety to enemy characteristics in your game not only enhances the gameplay experience but also introduces strategic depth that keeps players engaged. In this article, we’ll dive into the implementation of a simple yet effective feature — shields for enemies. This mechanic allows certain enemies to withstand an extra hit before being destroyed, adding an extra layer of challenge and strategy to the game.

The Basic Setup

Let’s start by setting up our enemies to potentially have shields. The shield will be a child object of the enemy GameObject, making it easy to activate or deactivate as needed. By default, the shield will be inactive. Here’s a quick overview of how to set this up:

  1. Create the shield as a child object: This can be a sprite or any visual indicator that represents the shield.
  2. Set the shield inactive by default: In Unity’s Inspector, uncheck the active box for the shield object.

The Spawn Manager

In a game, the spawner is responsible for generating enemies. We’ll tweak our spawn logic to activate the shield for every third enemy spawned. Here’s a sample code snippet from the SpawnManager class:

private int _count = 1;

private IEnumerator SpawnEnemyRoutine()
{
yield return new WaitForSeconds(3.0f);
while (!_stopSpawning)
{
GameObject newEnemy = Instantiate(_enemyPrefab, _randomPos, Quaternion.identity);
newEnemy.transform.parent = _enemyContainer.transform;
if (_count % 3 == 0)
{
newEnemy.transform.GetChild(0).gameObject.SetActive(true);
}
_count++;
yield return new WaitForSeconds(5);
}
}

This code ensures that the shield is activated for every third enemy by checking if _count % 3 == 0. The modulo operator % is used here to check for divisibility by 3.

The Enemy Class

Now, let’s handle how an enemy reacts to being hit. If the enemy has its shield active, the first hit will deactivate the shield instead of destroying the enemy. Here’s how you can implement this in the Enemy class:

private GameObject _enemyShield;

void Start()
{
_enemyShield = this.gameObject.transform.GetChild(0).gameObject;
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player" || other.tag == "Laser")
{
if (other.tag == "Player")
{
Player player = other.transform.GetComponent<Player>();
if (player != null)
{
player.Damage();
}
}
DestroyEnemy();
if (_player != null && other.tag == "Laser")
{
_player.AddScore(10);
}
}
}
void DestroyEnemy()
{
if (!_enemyShield.activeSelf)
{
_anim.SetTrigger("OnEnemyDeath");
_audioSource.Play();
_speed = 0;
Destroy(this.gameObject, 2.0f);
}
else
{
_enemyShield.SetActive(false);
}
}

The DestroyEnemy method checks if the shield is active using _enemyShield.activeSelf. If the shield is active, it's simply deactivated. Otherwise, the enemy is destroyed.

Improvements and Further Considerations

This basic implementation introduces the shield mechanic efficiently but can be extended in several ways:

  • Visual and Audio Feedback: Implement visual and audio cues when a shield is hit to enhance player feedback.
  • Varying Shield Strength: Instead of a single-hit shield, introduce shields with varying strengths that can withstand multiple hits.
  • Shield Regeneration: Implement a mechanic where shields can regenerate over time, adding an extra layer of strategy in prioritizing which enemies to attack.

Introducing shields to enemies in your game can significantly impact the gameplay experience, adding depth and requiring players to adopt new strategies. The implementation outlined above provides a solid foundation, but don’t hesitate to experiment and expand upon it to best fit your game’s design. Remember, the key to engaging game design is continually introducing new challenges and mechanics that keep the player invested and intrigued.

--

--

Damian Dąbrowski
Damian Dąbrowski

Written by Damian Dąbrowski

Hi, I’m Damian, an Electrical Power Engineer, who loves building AI powered apps.

No responses yet