I think most of the top FPS games create them from the client and send the data to the server to replicate to other clients. To put this in perspective:
Client creates bullet
Client sends data like origin, end position and other necessary information.
Server receives data and sends data to other clients to replicate
Other clients replicate bullet using the data
The client is also in charge of hit detection and you can use raycasting to achieve this. Using the client for hit detection often comes at a security risk but there are some sanity checks you can add on the server to make sure it’s not easily exploitable (making sure the weapon has ammo, checking line of sight from the origin of the bullet to the player that was hit, checking if the player is reloading, etc).
What do you mean firing it more than once? Itt should only be fired once per bullet on the server.
-- Client
ReplicateBullet:FireServer(Origin, EndPos)
ReplicateBullet.OnClientEvent:Connect(function(Origin, EndPos)
-- Use Origin and EndPos to simulate the bullet on the client
end)
-- Server
ReplicateBullet.OnServerEvent:Connect(function(player, Origin, EndPos)
-- Do sanity checks as well, this is just demonstration
ReplicateBullet:FireAllClients(Origin, EndPos)
end)
If you are creating a hitscan type system, bullets should be purely on the Client whenever the Player fires their weapon, you will typically see visible bullets as just pure detail in many games, and in many games, it gives you the ability to turn off bullets, for performance.
Common methods for this is to use:
Beams
Have Attachments between the Origin, and the Destination of the Ray, you can then se the speed of the texture to go really fast, and then delete the beam, shortly after,
Parts
You are able to Visualize the Path of the Ray towards on Object by doing simple math, there are already plenty of topics that cover this.
If you are creating a system using projectiles, you will use the Server for this, Apply a Network Ownership to the Projectile, and then have it move either using Constraints, or RunService so the bullet can travel.