§ How to · with Picoo

How to make a gun in Roblox Studio

By Sametcan Tasgiran, Founder & Developer·Published ·Updated

A gun is where client trust becomes free kills: if the client reports the hit, the client decides who dies.

The Tool, the Handle configuration, and the damage validation are three separate things people get wrong — usually in that order.

Equippable Tool

A Flamethrower Tool in StarterPack whose Handle is an unanchored Part styled as a dark metal barrel. At Play, a script welds a glowing muzzle, a fuel tank and a grip onto it.

Server-authoritative damage

The client sends where it fired from and which way it aimed. The server works out who was hit and applies the damage.

Rate limit + origin check

The server drops a shot if the player is not holding the weapon, fires more often than the rate limit allows, or claims an origin more than 18 studs from their HumanoidRootPart.

Range and cone

Cone mode, the default, hits every Humanoid within 45 studs and within 35° of the aim for 12 damage, up to ten times a second while the trigger is held.

Fire burst for everyone

Each accepted shot spawns a fire particle burst from the server, so every player sees the spray.

Reskinnable

Bolt mode fires a travelling neon projectile instead (a Blaster by default: 35 damage, 250-stud range). Name, damage, range, cone angle, fire rate, bolt speed and colours are all settings you can ask for in the prompt.

Files Picoo ships for this prompt

5 files · 144 lines · one recipe call

ServerScriptService.FlamethrowerServer

The authority: checks the tool, fire rate and origin, spawns the fire burst, and damages every Humanoid in the cone.

71 lines

StarterPack.Flamethrower.FlamethrowerLocal

While the trigger is held, sends the Handle position and the aim toward the mouse every 0.1 seconds.

34 lines

StarterPack.Flamethrower.FlamethrowerCosmetic

At Play, welds a neon muzzle, a fuel tank and a grip onto the Handle so it does not look like a grey brick.

39 lines

StarterPack.Flamethrower (Tool + Handle)

The Tool and its Handle Part, sized and coloured as a metal barrel in Edit mode.

instance

ReplicatedStorage.Remotes.FlamethrowerFire

RemoteEvent the client fires with its origin and aim direction.

instance

Sample output: ServerScriptService.FlamethrowerServer

FireEvent.OnServerEvent:Connect(function(player: Player, origin: Vector3, direction: Vector3)
	local character = player.Character
	if not character then return end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid or humanoid.Health <= 0 then return end
	local tool = character:FindFirstChildOfClass("Tool")
	if not tool or tool.Name ~= WEAPON_NAME then return end
	if typeof(origin) ~= "Vector3" or typeof(direction) ~= "Vector3" then return end

	local now = tick()
	if lastFire[player.UserId] and (now - lastFire[player.UserId]) < TICK_RATE * 0.7 then return end
	lastFire[player.UserId] = now

	local root = character:FindFirstChild("HumanoidRootPart") :: BasePart?
	if not root or (origin - root.Position).Magnitude > 18 then return end
	local dir = direction.Unit

	spawnConeVFX(origin, dir)

	for _, hum in ipairs(workspace:GetDescendants()) do
		if hum:IsA("Humanoid") and hum ~= humanoid and hum.Health > 0 then
			local hRoot = hum.Parent and hum.Parent:FindFirstChild("HumanoidRootPart") :: BasePart?
			if hRoot then
				local toTarget = hRoot.Position - origin
				local dist = toTarget.Magnitude
				if dist > 0 and dist <= RANGE and dir:Dot(toTarget.Unit) >= COS_LIMIT then
					hum:TakeDamage(DAMAGE)
				end
			end
		end
	end
end)

Building a gun in Roblox Studio

Guns fail in three distinct places, and most tutorials only cover the first one.

The first is the Tool itself. A Roblox Tool needs a BasePart child named exactly "Handle", and that part has to be unanchored. Leave it anchored and the weapon equips while the model stays hanging in the air where you built it. None of this errors; it just looks broken.

The second is who decides what got hit. The convenient design is for the client to raycast and tell the server "I hit this player", and it is the reason so many Roblox shooters are trivially exploitable. That code runs on the player's machine, so the message can say anything: everyone, at once, for any damage. The fix is a boundary, not a check: the client sends where it fired from and which way it aimed, the server confirms that origin is next to the player's character, and the server works out the hit. The client can still aim anywhere; it cannot report a hit.

The third is rate. Without a server-side fire-rate timestamp, a modified client fires every frame. Same shape as a cooldown, same reason it has to live on the server.

Picoo's projectile_weapon recipe is built on those three rules. Ask for a flamethrower, a blaster, a laser gun or "a gun that shoots" and it puts the Tool and its Handle in StarterPack, a server Script in ServerScriptService and a RemoteEvent in ReplicatedStorage.Remotes. The default Flamethrower checks the tool, the fire rate and an origin within 18 studs of the player, then damages every Humanoid within 45 studs and 35° of the aim. Bolt mode fires a travelling projectile instead. Both spawn their effects on the server, so every player sees the same shot.

See more on the Luau generator, the AI Luau script writer, the 3D model generator and the game builder, read how Picoo compares with ChatGPT, or browse the full blog.

Frequently asked

Why does my Roblox gun not appear in the player's hand?+

The Handle. A Tool needs a BasePart child named exactly "Handle", and it must be unanchored. An anchored Handle is the classic one: the Tool equips and the model stays floating where you built it. Setting CanCollide false and Massless on the Handle also keeps it from bumping into things and dragging on the character.

Should the client or the server detect hits?+

The server. If the client reports what it hit, an exploiter reports hitting everyone at once from across the map, and no amount of client-side validation stops it, because that code runs on their machine. Send the aim, let the server work out the hit.

Does server-side hit detection make shooting feel laggy?+

Damage lands one network round trip after the trigger is pulled. In this recipe the fire burst is also spawned by the server, so the shooter sees it after that same round trip. For an instant effect on the shooter's own screen, ask for a local muzzle flash in a follow-up prompt; the damage stays on the server either way.

How do I stop rapid-fire exploits?+

Keep the fire rate on the server with a per-player timestamp, exactly like a cooldown. A client-side debounce is a UI convenience; the server's is the rule. Validate the origin too: this recipe drops any shot whose origin is more than 18 studs from the player's HumanoidRootPart, so a spoofed origin cannot fire from across the map.

Can I make it a laser or a water gun instead?+

Yes. Ask for a laser gun, a blaster or a water gun. Bolt mode, a travelling projectile that damages the first Humanoid it touches, suits a laser or blaster; cone mode in a new colour suits a water gun. You can set damage, range, fire rate and colours in the same prompt.

Related Picoo prompts