Best way to make bullets for guns/detect shots

I just want a basis of what people typically would do for guns? I have never attempted to code an FPS but I’ve always wanted to. What is the best way to make bullets and detect shots? Body movers on an actual part? Like, doing rays or something? I just want a good basis to start programming guns with.

1 Like

There’s a few different ways to do it based on desired results.

BodyMovers on parts is a great start. As is raycasting.
Camera mode is going to be a big part of it. Getting the right camera is key.

When figuring out the bodymovers, understanding CFrame and LookVectors is recommended. As is understanding the camera and screen boundaries and calculating the pointing angle of things, as well as the pointing direction of the camera.

Since you’ll be working with client-side data, you’ll have to send information from the client to the server. Which will require Remote Events.

So instead of using mouse position it’d be mouse angle? I’m a little lost of what you mean by that.

To detect shots, you can fire a RemoteEvent when someone clicks with the gun equipped (Warning, if the FPS will not be solo only then have in mind the remote event triggers when ANYONE on the server shoots.) or just make a function and try to fit the whole code on a single script. Best way to make bullets? If it is a proyectile, I’d recommend making a part appearing right on the tip of the gun when the RemoteEvent or function is triggered, and keep it gliding to the direction the gun was pointing at. Also make a particleEmitter appear on the tip of the gun and enable the particle for .2 seconds. If it is any other kind of weapon then just do the particle thing again and make it so anything that was on the aim of the gun will be detected, and if it is a humanoid, decrease health. That are my initial ideas. As soon as I get a way to code that, I’ll talk to you. Oh and to detect the aim, I think you can make a little crosshair with a ImageLabel, and that’d be the aim. You can also just detect the mouse position if it is in first person only.

I made mine using Raycasting, you can see what I used.

RemoteEventFire.OnServerEvent:Connect(function(plr, MouseClickPos, BulletPartSignifierPos, Damage, HeadShotDamage) --Gathers all info
	local function FireBullet()
		local rayOrigin = BulletPartSignifierPos --RayOrigin is bullet muzzle
		local rayDirection = ((MouseClickPos - rayOrigin).Unit) * 1000 --Goes towards the mouse click vec3 position and adds 1000 studs to its length

		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {Parent.Parent.BulletPartSignifier, Parent} --Removes bullet muzzle from raycast instances
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

		if raycastResult and raycastResult.Instance then --If it gets a result, and there's an instance
			print(raycastResult.Instance)
			local bullet = Instance.new("Part") --Creates a part
			bullet.Name = "Bullet"
			bullet.CanCollide = false
			bullet.Anchored = true	
			bullet.BrickColor = BrickColor.new("New Yeller")
			bullet.Material = Enum.Material.Neon
			bullet.Parent = workspace
			local Center = (raycastResult.Position + BulletPartSignifierPos) / 2 --Moves it to the center of the two parts.
			bullet.Size = Vector3.new(0.01, 0.01, (BulletPartSignifierPos - raycastResult.Position).Magnitude) --Makes the size of it big enough so that it reaches from muzzle to the part mouse touched.
			bullet.CFrame = CFrame.lookAt(Center,raycastResult.Position) --Makes the bullet look at where the mouse touched, aka the raycastResult Posiiton.
			if raycastResult.Instance.Parent:FindFirstChild("Humanoid") and raycastResult.Instance.Name == "Head" and raycastResult.Instance.Parent.Name ~= plr.Name then --If it's a headshot
				raycastResult.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(HeadShotDamage) -Takes headshot Damage
				HitPart = "Head"
				RemoteEventFire:FireClient(plr, HitPart)
			elseif raycastResult.Instance.Parent:FindFirstChild("Humanoid") and raycastResult.Instance.Parent.Name ~= plr.Name then --If it hits anything besides the head
				HitPart = "Body"
				RemoteEventFire:FireClient(plr, HitPart)
				raycastResult.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(Damage) 
			end
			wait(0.05)
			bullet:Destroy()
		else --If it doesn't have a raycast, aka touching the skybox, it just creates a line into the air.
			print(raycastResult.Instance)
			local bullet = Instance.new("Part")
			bullet.Name = "Bullet"
			bullet.CanCollide = false
			bullet.Anchored = true	
			bullet.BrickColor = BrickColor.new("New Yeller")
			bullet.Material = Enum.Material.Neon
			bullet.Parent = workspace
			local Center = (MouseClickPos + BulletPartSignifierPos) / 2
			bullet.Size = Vector3.new(0.01, 0.01, (BulletPartSignifierPos - MouseClickPos).Magnitude)
			bullet.CFrame = CFrame.lookAt(Center, MouseClickPos)
			wait(0.05)
			bullet:Destroy()
		end
	end
	FireBullet()
end)

Due to the fact that BasePart.Touched is extremely spotty, I was forced to use raycasting for damage dealing.

2 Likes

The thing w/ raycast is its instant. I want stuff like bullet drop and I don’t want to make it just zip across the map on click.

Use fastcast for that. It pretty much handles everything for you.

I’ve never seen that… Will definitely look into it!