How to Create Player Shooting for FPS Game with ROBLOX

In this comprehensive guide, we will delve into the topic of creating player shooting mechanics in a first-person game using Roblox Studio. The tutorial will be split into three parts. In the first part, we will set up the first-person perspective and create the player’s gun. In the second part, we will implement the shooting functionality, and finally, in the third part, we will work on the reload mechanism. You are expected to be familiar with the following concepts:

  • Basic knowledge of Roblox Studio
  • Fundamentals of Lua scripting

Project Files

While you will be creating your own Roblox project, we have included a full copy of the scripts used in this tutorial. The download link is given below for your reference.

Download Project Files Here

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Player Shooting – Part 1

In this lesson, we’re going to set up our players.

We want our players to have a first-person view.

To do this, select the StarterPlayer folder in the Explorer window. Now, in the Properties window, change the CameraMode attribute from ‘Classic‘ to ‘LockFirstPerson‘ and the CameraMaxZoomDistance to 0.5:

Properties window

Creating the Player’s Gun

In the Toolbox, search for a handgun. Drag and drop the ‘Working Handgun‘ to the game view:

Working Handgun

You’ll see there’s a bunch of stuff included in the handgun model in the Explorer window:

Explorer window

Delete all of them except the Handle one. Inside Handle, leave only the sound effects:

Handle

Setting the GunScript

Click on Handgun and create a new LocalScript called ‘GunScript‘.

Let’s define the variables we’re going to need:

-- Parts
local Weapon = script.Parent
local Camera = workspace.CurrentCamera

-- Sound Effects
local ShootSFX = Weapon.Handle.FireSound
local ReloadSFX = Weapon.Handle.Reload

-- Replicated Storage
local ReplicatedStorage = game.ReplicatedStorage
local DamagePlayerEvent = ReplicatedStorage:WaitForChild("DamagePlayer")

We have our weapon (the handgun itself) and the camera which in our case is the target (as the player is shooting at whatever is in the spot they are hovering their mouse over). Regarding sound effects, we have both shooting and reloading sounds.

Now, we need to add a damage player event.

Create a RemoteEvent under ReplicatedStorage called ‘DamagePlayer‘. A remote event allows the server to communicate with the client. In our game, the players will inform the server of who they shot and how much damage was dealt to that player.

Next, we’ll specify the damage of each shot, the current and reserved ammo, and whether the player can shoot (false when reloading the gun):

-- Damage
local Damage = 25

-- Ammo
local CurMagAmmo = 12
local MagSize = 12
local ReserveAmmo = 48

local CanShoot = true

Following, when the player equips the weapon, we’re going to call an event:

local function Shoot (mouse) 

end

local function Reload ()
    
end

Weapon.Equipped:Connect(function(mouse)
  
    mouse.Button1Down:Connect(function()

        if CanShoot == true then
            if CurMagAmmo > 0 then
                Shoot(mouse)
            elseif ReserveAmmo > 0 then
                Reload()
            end
        end

    end)
  
end)

In this event, we’re listening to when the player shoots. If they have enough ammo, the shot is accounted for. Otherwise, we reload the gun.

In the next lesson, we’ll be working on our Shoot function so we’re able to deal damage to players.

Player Shooting – Part 2

In this lesson, we’re going to continue implementing our GunScript by setting up the functionality for the player to shoot.

Our Shoot function is called whenever the left mouse button is clicked.

The first thing we’re going to do is play the sound effect of the shot, then update the current amount of bullets in the magazine. After that, we get the target object of our shot to verify if it’s one of the other players (thus, the humanoid child of our target):

local function Shoot (mouse)

    -- play the SFX
    ShootSFX:Play()
  
    CurMagAmmo -= 1
  
    local target = mouse.Target
    local humanoid = nil

    -- get the target humanoid
    if target.Parent:FindFirstChild("Humanoid") then
        humanoid = target.Parent:FindFirstChild("Humanoid")
    elseif target.Parent.Parent:FindFirstChild("Humanoid") then
        humanoid = target.Parent.Parent:FindFirstChild("Humanoid")
    end
  
end

If our bullet catches the other player in their hair or other accessories then we need to access the Parent of the Parent of our target instead to be able to get hold of the actual humanoid object.

Now that we got our target humanoid, we need to tell the server that we’ve hit them:

local function Shoot (mouse)

    -- play the SFX
    ShootSFX:Play()
  
    CurMagAmmo -= 1
  
    local target = mouse.Target
    local humanoid = nil

    -- get the target humanoid
    if target.Parent:FindFirstChild("Humanoid") then
        humanoid = target.Parent:FindFirstChild("Humanoid")
    elseif target.Parent.Parent:FindFirstChild("Humanoid") then
        humanoid = target.Parent.Parent:FindFirstChild("Humanoid")
    end
  
    if humanoid then
        local hitPlayer = game.Players:GetPlayerFromCharacter(humanoid.Parent)
        DamagePlayerEvent:FireServer(hitPlayer, Damage)
    end
  
    UpdateAmmoText()
  
end

Note that the humanoid or character is the physical player in our game world while the player we’re accessing here is the data associated with that humanoid.

We then store the player information in the hitPlayer variable and we fire our DamagePlayerEvent sending the hitPlayer alongside the damage dealt as parameters.

Setting up the DamagePlayerEvent

Create a new script under ServerScriptService in the Explorer window and call it ‘PlayerDamageManager‘.

We’re basically only going to listen to the DamagePlayerEvent:

local DamagePlayerEvent = game.ReplicatedStorage.DamagePlayer

DamagePlayerEvent.OnServerEvent:Connect(function(attacker, hitPlayer, damage)
  hitPlayer.Character.Humanoid:TakeDamage(damage)
end)

Here, we need to add in as the first parameter the attacker (namely the player that is calling this event) as it is automatically passed on when we call FireServer in the client.

Testing our Shooting Function

Let’s move our Handgun object from the Workspace to the StarterPack folder so every player will start the game with a gun inside their inventory:

StarterPack

Handgun object

By pressing 1 we equip it and we can shoot until we’re out of bullets.

Let’s test our game with multiple players now.

Go to the Test tab and select 2 players:

Test tab

We see that we’re able to deal damage to the other player as expected:

deal damage

Later on, we’ll add a scoreboard to our game so the players can keep track of their kills, deaths, and how many times they’ve won.

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.

Player Shooting – Part 3

In this lesson, we’ll implement the reloading of the gun in our game.

The Reload function is called when we’re out of ammo but we have some reserve ammo left.

local function Reload ()
  
    CanShoot = false
  
    ReloadSFX:Play()
    wait(ReloadSFX.TimeLength)
  
    CanShoot = true
  
    CurMagAmmo = MagSize
    ReserveAmmo -= MagSize
  
end

We start by setting CanShoot to false, we play the sound effect and put the function on wait until the reload sound finishes. We then set CanShoot to true again, refill the player’s magazine and subtract from their reserve ammo.

Now, we need to create a new ScreenGui under the StartGui folder to show us how much ammo we currently have:

ScreenGui

Name it ‘AmmoGui‘.

Next, create a TextLabel under AmmoGui called ‘AmmoText‘. Set its BackgroundTransparency property to 1. We can increase the TextSize to ‘50‘ and the TextColor3 to white. Change its TextAlignment to ‘Left‘ as well.

We can also set the Text to say something like “12/100” for now:

TextLabel

Let us actually move our AmmoGui to the ReplicatedStorage service, instead of leaving it in the StarterGui:

ReplicatedStorage

We’re doing that because we’ll be creating and destroying this Gui whenever we equip and unequip our gun.

Go back to the GunScript and create a local player GUI:

-- GUI
local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
local AmmoText = nil

Let’s set our AmmoText in the Weapon.Equipped event:

Weapon.Equipped:Connect(function(mouse)
  
    local guiClone = game.ReplicatedStorage.AmmoGui:Clone()
    guiClone.Parent = PlayerGui
    AmmoText = guiClone.AmmoText
  
    UpdateAmmoText()
  
    mouse.Button1Down:Connect(function()
  
        if CanShoot == true then
            if CurMagAmmo > 0 then
                Shoot(mouse)
            elseif ReserveAmmo > 0 then
                Reload()
            end
        end
    
    end)
  
end)

Our UpdateAmmoText function concatenates the current ammo in the magazine to the reserve ammo into a string that is set to our AmmoText as follows:

local function UpdateAmmoText ()
  
    if AmmoText ~= nil then
        AmmoText.Text = CurMagAmmo .. " / " .. ReserveAmmo
    end
  
end

With the UpdateAmmoText function implemented, add an  UpdateAmmoText() call at the end of both Shoot and Reload functions.

Finally, we need to destroy our ammoGui when unequipping the gun:

Weapon.Unequipped:Connect(function()
    PlayerGui.AmmoGui:Destroy()
end)

By testing it, we see that the text is correctly updating the number of bullets we have left:

testing

Conclusion

Congratulations! You have now successfully created a first-person shooter mechanic in a Roblox game. Through this tutorial, you have learned how to create a basic shooting mechanism, introduce ammunition concepts, and even include a reloading feature. You’ve taken a big step towards creating a more immersive and engaging gaming experience for your players!

The concepts, ideas, and scripting techniques that you’ve learned here can be widely applied across various projects – not just limited to shooter games. Always remember to keep experimenting and refining your code. By doing so, you can achieve the exact gameplay that you envision. We hope that this tutorial has been insightful and fun.

We look forward to seeing what incredible games you will create using Roblox Studio!

Want to learn more? Try our complete MAKE A FIRST-PERSON SHOOTER WITH ROBLOX course.