Polishing the UX of a 2D Space Shooter Player Script

Alberto Garcia
3 min readJan 30, 2023

--

To polish the user experience of the current state of the 2D Space Shooter, some implementations will be further refined to create more skilled ways of playing the game. In this article I will cover how to create:

  • Manual boost
  • Shield health
  • Ammo count

Afterwards, two more collectibles will be implemented to pick up ammo as well as health packs.

For the manual boost implementation, the player will press down the left shift key to speed up the player and return to normal speed when the key is released using a wider variety of Input Types.

 //boost
if (Input.GetKeyDown(KeyCode.LeftShift))
{
_thrusterFire.SetActive(true);
_speed *= _speedMultiplier;
}
else if (Input.GetKeyUp(KeyCode.LeftShift))
{
_thrusterFire.SetActive(false);
_speed /= _speedMultiplier;
}

This implementation goes inside the CalculateMovement() method and simply multiplies and divides the player’s speed while toggling on and off the boost indicator.

For the shield health, an handler for the shield’s sprite renderer is needed to change the color along the shield’s health integer.

public SpriteRenderer _shieldRenderer;
private int _shieldHealth = 3;

public void Damage()
{
if (_ShieldEnabled == true)
{
_shieldHealth--;

if (_shieldHealth == 2)
{
_shieldRenderer.color = Color.green;
}
else if (_shieldHealth == 1)
{
_shieldRenderer.color = Color.magenta;
}
else if (_shieldHealth == 0)
{
_shieldRenderer.color = Color.red;
StartCoroutine(ShieldTurnOff());
_ShieldEnabled = false;
}
return;
}
}
public void ActivateShield()
{
_ShieldEnabled = true;
_shieldGameObj.SetActive(true);
_shieldHealth = 3;
_shieldRenderer.color = Color.cyan;
}

This is now the damage sequence that the shield receives and the updated form of activating a shield, always getting the color of the sprite renderer equal to the max health color.

For the ammo count, implementation was longer and optimized using an object pool instead of instantiating and destroying player’s lasers. A new script called Object Pool is created and attached to the player, since we are giving the player a pool of lasers to shoot.

public class ObjectPool : MonoBehaviour
{
public static ObjectPool SharedInstance;
public List<GameObject> _pooledObjects;
public GameObject _objectToPool;
public int amountToPool;

private void Awake()
{
SharedInstance = this;
amountToPool = 15;
}
private void Start()
{
_pooledObjects = new List<GameObject>();
GameObject tmp;
for(int i = 0; i < amountToPool; i++)
{
tmp = Instantiate(_objectToPool);
tmp.SetActive(false);
_pooledObjects.Add(tmp);
}
}

public GameObject GetPooledObject()
{
for(int i = 0; i < amountToPool; i++)
{
if (!_pooledObjects[i].activeInHierarchy)
{
return _pooledObjects[i];
}
}
return null;
}
}

Then this implementations was used to replace the instantiation of laser prefabs and simply enable and disable objects from the pool.

private int _maxAmmo = 15
private int _currentAmmo;
private bool _isAmmoReady = true;

//define _currentAmmo to equal _maxAmmo at start and when reloading
void ShootLaser()
{
//tripleShot if statement and then normal shooting...

else if (Input.GetKeyDown(KeyCode.Space) && _laserCanFire && _isAmmoReady)
{
if(_currentAmmo == 15)
{
_ammoIndicatorRenderer.color = Color.green;
}
GameObject bullet = ObjectPool.SharedInstance.GetPooledObject();
if (bullet != null)
{
bullet.transform.position = transform.position + new Vector3(0, 1.05f, 0);
bullet.transform.rotation = Quaternion.identity;
bullet.SetActive(true);
}
_currentAmmo--;
_audioSource.Play();
_laserCanFire = false;
StartCoroutine(LaserDelay());
if (_currentAmmo == 10)
{
_ammoIndicatorRenderer.color = Color.blue;
}
else if (_currentAmmo == 5)
{
_ammoIndicatorRenderer.color = Color.red;
}
else if(_currentAmmo == 0)
{
_isAmmoReady = false;
_ammoIndicator.SetActive(false);
}
}
}
public void ReloadAmmo()
{
_currentAmmo = _maxAmmo;
_ammoIndicatorRenderer.color = Color.green;
_ammoIndicator.SetActive(true);
_isAmmoReady = true;
}

This reload mechanic was achieved thanks to Brackey’s awesome video on reloading. Other places where laser used to get destroyed now disabled the laser prefab. On the next article I will go over how to provide ammo collectibles as well as health packs to restore health.

All of this implementations give the player more things to be careful of and try to be more precise during game play as infinite shooting is not allowed anymore, ammo must be picked up, yet, the shield now count as three hits, giving a player another way of being safer, as well as having a manual boost ready at hand.

This way of handling shooting should optimize the experience as the player will not be able to create and destroy hundreds of laser prefabs within a minute.

Signifier for Ammo Count

--

--

Alberto Garcia
Alberto Garcia

No responses yet