Time to add a new PowerUp to our game. Problem is, we’ve run out of pre-built sprites. We have two obvious choices. The first is to search for suitable sprites from an asset store such as GameDevHQ’s Filebase, or the Unity Asset Store. The second choice is to create our own. Since I have no experience creating my own artwork, naturally, I chose the harder, second choice. At least harder for me. The reason for my choice is I want the new PowerUp to have the same look as the existing ones. So, in this particular case, the artwork problem should mostly be solved making it pretty straight forward. All I have to do is copy one of the existing sprites, change the color and the text.
Sure, go ahead. I hear you laughing. Obviously, I have a lot to learn. For now, however, I’ll let my art lesson story wait for another day. Suffice to say, I now have a new sprite in [mostly] the same style as the ones originally provided. So, let’s pick up the story from there.
Our new sprite is saved as sixteen png image files. We need to bring them into our Unity project. In Unity, this means we need to “Import” them. And in Unity, these external objects are called “Assets.” Create a new folder to hold them. In fact, we’ll create a folder called Sprites and then another called Ammo. Select the Ammo folder, then, from the main menu, Assets -> Import New Assets. Navigate to the folder with our image files and select all the images. They should appear in our folder.
One thing to note is how they are actually imported.
Notice the images in our imported folder have a black background and no child object. If you select one and look in the Inspector you will see the Texture type is set to “Default.” We need to reset the Texture Type. We can do this for every image all at once by selecting all of them in the Project view. Then, in the Inspector change the Texture Type from Default to “Sprite (2D and UI).
The good news is we get to cheat now. We’ve already created several animations, and we were smart enough to write down how we did it. We’ll follow those directions to create our new PowerUp prefab just like we did the other three. We’ll list the abbreviated steps.
- Create an empty game object and name it AmmoPowerUp
- Create an unique tag name for it and set the tag
- Reset the Transform component
- Position (0,0,0)
- Rotation (0,0,0)
- Scale (0.5, 0.5, 0.5)
- Drag the Powerup4_0008_001 image into the Sprite field of the Sprite Renderer component
- Set Sprite Render -> Additional Settings -> Sorting Layer to “Foreground”
- Add a Circle Collider 2D
- Change the Collider radius to match the others
- Select the “Is Trigger” field
- Add a RigidBody 2D
- Set the Gravity Scale to 0
- Select the Ammo PowerUp Game object
- Open the Animation Window (Window -> Animation -> Animation).
- Create a new animation. You should see text indicating it will be an animation for the Ammo PowerUp. Click the “Create” button.
- Save the new file in our Animations folder and name it in a manner consistent with the others. e.g. AmmoPowerUp_anim.anim
- Drag the collection of images into the Animation Window, hit the record button and play, then stop and save it. Make sure the Controller field is populated in the Animator component is populated with our newly created Ammo Animation controller.
- Add the PowerUp script. Note, this is the same script added to all the other PowerUps. No modifications will be needed to this script.
- Select the AmmoPowerUp game object and drag the power_up_sound into the My Audio Clip field of the PowerUp Script
- Update the Player and Weapons scripts to include the new behavior needed
For now, we will keep it simple. The Weapons script will determine the effects of the Ammo Collectible and have a public method to invoke it. The Player script will detect the collision and invoke the method.
[SerializeField] private int ammoCollectible = 15;
public void CollectAmmo() { AmmoCount = AmmoCount + ammoCollectible; }
private void OnTriggerEnter2D(Collider2D other)
{
switch (other.tag)
{
case "Enemy":
TakeDamage();
break;
case "Enemy Laser":
if (other.transform.parent.GetComponent<EnemyFire>().HasHit) { return; }
other.transform.parent.GetComponent<EnemyFire>().HasHit = true;
TakeDamage();
break;
case "TripleShotPU":
if (!myWeapons.TripleShotEnabled) { myWeapons.TripleShotEnabled = true; }
break;
case "SpeedPU":
if (speedUp == 0) { StartCoroutine(PowerUpSpeed()); }
break;
case "ShieldPU":
if (!shieldAnim.IsActive) { shieldAnim.IsActive = true; }
break;
case "AmmoPU":
myWeapons.CollectAmmo();
break;
default:
break;
}
}
Finally, we need to add our new PowerUp to the array of power ups in the Spawn Manager.
Our Spawn Manager should now be able to spawn the ammo collectible. Our Player should be able to detect it and the Weapons should update the ammo count.
We will make one small change to our Weapons script while we are at it though. Every time we change our ammo count, we also have to change the display of our score in the UI Manager. Well, that makes the UI display seem like nothing more than a visual representation of the ammo count. This makes it seem more sensible for our AmmoCount()
property to notify the UI rather than having to do that as a second step. So, let’s remove all the calls to uiManager.AmmoCount(AmmoCount)
and move it to the AmmoCount()
setter instead.
[SerializeField] private int ammoStartCount = 26;
[SerializeField] private int ammoCount;
private int AmmoCount
{
get { return ammoCount; }
set {
ammoCount = value;
ammoCount = (ammoCount < 0) ? 0 : ammoCount;
uiManager.AmmoCount(AmmoCount);
}
}
void Start()
{
NullCheckOnStartup();
AmmoCount = ammoStartCount;
}
Lock and load, now let’s go…!