The simplest way to create a First Person Shooter! (Part 3)

In just a few steps, learn how to make your very own First Person Shooter with multiple Guns, with different shooting ranges and ammunition types in Unity. Practical explanation + Code included.

Seemanta Debdas
Eincode
7 min readFeb 14, 2022

--

This is the third part of a three-part series covering the Simplest Way to Make a First Person Shooter. It’s highly recommended that you go through the last two parts before continuing with this one.

In this section, we’re going to cover the following topics:

→ Basic Ammo Functionality!
→ Different Ammo types!
→ Simple reloading functionality!

With that out of the way, let’s get started!

Resources

GitHub Repository: Blog-FirstPersonShooter

Full RPG game course: https://academy.eincode.com/courses/the-complete-unity-guide-3d-beginner-to-rpg-game-dev-in-c

1. Basic Ammo Functionality!

We’ll be adding more layers as we go along but first, let’s create a Basic Ammo Functionality that lets the Player shoot only when there’s ammo left.

First, Create a Script:
Right Click on the Project Panel → Create → C# Script → Name it “Ammo.”

This script will sit on our Player. Select the Player, and in the Inspector panel, click on Add Component → Search “Ammo” and click enter.

Open the Ammo Script, and inside,

  1. Create a Serialized variable for ammoCount.
  2. Create a public function for getting ammoCount→ GetAmmoCount().
    We’ll use this function to get the current ammo count from each Weapon prefab. This will also be essential to check whether we have ammo before shooting.
  3. Create a public function for reducing the ammoCount as we shoot → ReduceAmmoCount(). Every time we shoot, the ammoCount will be reduced by 1.

The script should look something like this:

Now that we’ve set up the Ammo Script, let’s move over to the Weapons Script and reference the Ammo Script. We can do that by serializing a variable of type Ammo.

Then drag in the Game Object that has Ammo Script added to it → , the Player Game Object.

Now that we’ve got a reference to ammo, we can implement the functionality where we only shoot when ammo.GetAmmoCount() > 0 is true, that is, the Player still has some Ammo left.

Also, we want to reduce the ammo count by calling ammo whenever we shoot.ReduceAmmoCount().

Modify the Update function of the Weapon Script like this:

In the Shoot function, make the following changes:

In the Editor, set some value for ammoCount in the Ammo Script. Press play and see the ammoCount reduce as you shoot!

2. Different Ammo Types!

We will be changing the framework a bit in this section to make it more flexible.

So the concept behind this is we’re going to have

  1. Different ammoType for different Weapons. e.g., Bullets, Rockets, and Shells.
  2. The Player is going to have different ammoSlots. Each ammoSlot will have an ammoType and an ammoAmount.

To help you visualize:

NOTE: We’re not using Shells or Rockets in this project. They are just named as such for differentiating ammo types.

Enumeration to store Ammo Types

First, let’s create a script:
Right Click on the Project Panel → Create → C# Script → Name it “AmmoType.”

This will be an Enumeration that will store a list of all the Ammo Types.

Enum in C# is also known as enumeration. It is used to store a set of named constants such as season, days, month, size etc. The enum constants are also known as enumerators. Enum in C# can be declared within or outside class and structs.” ~ Javapoint

To create it, open the “AmmoType” script and replace everything with the following code:

Private Classes

Now let’s modify the “Ammo” Script to make Ammo Slots.

Ammo Slots will specify what Ammo Type has how much Ammo Count.

To create Ammo Slots, we must declare a private class inside the “Ammo” Script. This private class called “AmmoSlot” will only be visible to the “Ammo” script.

“AmmoSlot” is going to contain two variables:

  • one for the name of the Ammo Slot(name)
  • one for Ammo Type(ammoType)
  • one for Current Ammo Count(ammoCount)
  • one for Initial Ammo Count(initial Ammo Count)

Much like “[Serializable]” is used to view fields in Inspector. Also, since we want to view this in the Inspector panel, add “[System.Serializable]” on top of the private class. This allows us to view public classes in the Inspector.

Now make a Serialized Array of Ammo Slots to define the Ammo Type and Ammo Amount of each Ammo Slot from the Inspector.

Finally, remove the ammoCount variable earlier in the “Ammo” script because now we will be accessing it through AmmoSlot. This will cause some errors in GetAmmoCount() and ReduceAmmoCount() function. Comment them out. For now, we’ll come back to them later.

The code should look like this:

NOTE: This will also cause some issues in the “Weapons” Script. They will be resolved later on. Comment them out too.

Now, if we click on the Player in the Editor, we’ll see a list called “Ammo Slots,” whose initial size is 0. Set it to 3(for three different Ammo Types) and set the values as such:

This is a super flexible system. You can add more ammo slots for different ammo types if needed.

Setting up the Code

This section will ensure that each Weapon will be shooting from its type of ammo.

In the “Weapon” script, add an [SerializedField] of type AmmoType. This will let us specify which Weapon uses which AmmoType.

After this, select each Weapon, and in the Inspector panel, set the AmmoType of each Weapon.

Set this for all the Weapons

Head over to the “Ammo” script and “Weapon” script and uncomment the code that was commented on earlier and make the following changes:

To GetAmmoCount and ReduceAmmoCount, now we can’t simply ask for it because there are multiple AmmoTypes. Therefore we need to specify which Ammo Type we want to get or deduce.

To do this, add a parameter of type AmmoType for the functions: GetAmmoCount() and ReduceAmmoCount().

This script will still have some errors that will be revisited but first, let’s resolve the ones in the “Weapon” script.

In the “Weapon” script,
In the Update function, instead of calling ammo.GetAmmoCount() can now specify the Ammo Type by passing the ammoType variable that we serialized earlier.

Similarly, in the Shoot() function, instead of calling ammo.ReduceAmmoCount(), we can now specify the Ammo Type.

That should solve all the errors in the “Weapon” Script.

Back in the “Ammo” script,
In the GetInitialAmmoCount(AmmoType ammoType) and ReduceAmmoCount(AmmoType ammoType) functions, we need to return and reduce ammoCount of specified ammoType.

First, we need to get the slot that matches the specified AmmoType. From that slot, we can get the ammoCount.

To achieve that,

  1. Make a function called GetAmmoSlot(AmmoType ammoType) of type AmmoSlot. Notice that it takes in a parameter of type AmmoType.
  2. In the function, cycle through the Ammo Slots list, and if the AmmoType of the Slot matches the AmmoType of that has been passed in the function, then return that slot else return null.
  3. Finally, in the GetInitialAmmoCount and ReduceAmmoCount functions, we can get the ammoCount by first getting the Ammo Slot and then extracting the ammoCount from it.

It is a bit tricky to get this on the first try. Go through the section again, taking help from the visualization image at the very beginning.

3. Simple reloading functionality!

Once any Weapon runs out of bullets while shooting, there’s no way to reset the Current Ammo(ammoCount) back to Initial Ammo(initialAmmoCount). Let’s make some simple changes to make that possible.

In the Ammo Script, similar to the other functions, let’s make another function called ReloadAmmoCount(AmmoType ammoType).

This function gets the Ammo Slot whose ammoType matches the ammoType that has been passed in as a parameter. Then it sets the slot’s ammoCount = Slot’s initialAmmoCount. Thus, resetting the ammo.

Now, in the Update function of the Weapon script, we detect that if “R” is pressed, then we’ll call reload function:

Conclusion

With that, we conclude our three-part series!

You can check out the GitHub repo, where I’ve added a shooting animation and simple UI to show current bullets and added a bit of post-processing. You can study the project to know more about it.

Repository Link: Blog-FirstPersonShooter

If this simple Third Person Character Controller piqued your curiosity, then you should consider opting for The Complete Unity Guide 3D- Beginner to RPG Game Dev in C# offered by Eincode. This course features among the most immersive and practical resources out there.

This course is curated by experienced software engineer and freelance developer Filip Jerga. This course starts with the fundamentals. Then, it progresses gradually to eventually take its subscribers through the journey of developing their own RPG game by using Unity 2020 and C#!

Cheers!

Debdas

--

--

Seemanta Debdas
Eincode

Game Dev enthusiast contributing to the Gaming Industry!