How would i go about making a gun system like this?

Are you confusing the camera’s position for the hit position?

i dont really know, mean all i am is sending the ray over so i have no clue

Can you at least label the things you’re printing out?
Also apparently you aren’t even printing the hit location, only the ray

Also also you can always just refer back to the demo I sent for guidance

The main thing im looking at is the bottom print, all im printing is the instance its hitting, (removed the other prints right now), i just thought it would hit the instance thats under the cursor but the spawn location is pretty far from the cursor and its still hitting it

Code

Server

local Tool = script.Parent
local Event = Tool.MainEvent
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {}
Params.FilterType = Enum.RaycastFilterType.Blacklist

local function OnEquipped()
	local C = {}
	local Holder = Tool.Parent
	table.insert(C, Holder)
	for i, v in ipairs(workspace.Ignored:GetChildren()) do
		table.insert(C, v)
	end
	Params.FilterDescendantsInstances = C
end

local function Shoot(Player, ray)	
	local Rv = ray.Direction * 300
	local Raycast = workspace:Raycast(ray.Origin, Rv, Params)
	
	local HitPos = if Raycast then Raycast.Position else ray.Origin + Rv
	
	local ShootFrom = Tool.Handle.Attachment.WorldPosition
	
	local AimAt = HitPos - ShootFrom
	local HitDetection = workspace:Raycast(ShootFrom, AimAt * 2, Params)
	
	local ThingHit = if HitDetection then HitDetection.Instance else nil
	
	local PosHit = if HitDetection then HitDetection.Position else HitPos
	
	if ThingHit then
		print(ThingHit)
	end
end

Event.OnServerEvent:Connect(Shoot)
Tool.Equipped:Connect(OnEquipped)

Client

local Tool = script.Parent
local player = game.Players.LocalPlayer
local UIS = game:GetService("UserInputService")
local Event = Tool.MainEvent
local mouse = player:GetMouse()

script.Parent.Activated:Connect(function()
	local ray = workspace.CurrentCamera:ViewportPointToRay(mouse.X, mouse.Y)
	Event:FireServer(ray)
end)

Sorry if this isnt what you are asking for, dont really know what you mean here

Ah I see, I was talking about something else

The issue seems to stem from this:


Deriving the cursor position from mouse will respect the topbar offset, which is 36 pixels down, meaning that the ray will always be 36 pixels offset from the actual position. So you should’ve used UserInputService for this, which ignores the topbar offset.

Alright i switched it over to UIS and now uh
Idk cant really explain it in words so


Extremely confused now why the spawnlocation ceases to exist

Did you blacklist it from the raycast

Nope, it shouldn’t be blacklisted at all, and it hits once in the video not sure where i clicked for that though.

Try debugging it by spawning a temporary part on where the bullet should’ve hit and see if there’s anything wrong

Did this and saw the part spawning only in one area,

Apparently i didnt put the GetMouseLocation into the Activated function, so its all good now

Now, how would i create the bullet on the client so it doesnt look like its lagging behind like hell

When the player shoots, immediately create the clientsided bullet on their end (this means that the hitreg calculations will also need to be done on the client, but it will only be for GFX and has no actual effect on the bullet itself)
And for everyone else, the server will distribute the hitreg information and each client will create the tracer separately

You can once again refer back to the demo I sent for this, except that the demo doesn’t do what I just described in paragraph 1

So basically i gotta do everything thing i did on server, also on client?

Like FireAllClients?

Basically yeah

Well yes, but then it’s also going to fire back to the client who shot the bullet which will make it look like they shot twice
So you should instead manually fire the players

So Should i make it from scratch or can i just paste it over?

How would i do this?, never really did much else then firing all clients

You can paste it over, make changes to the variables if necessary

Use a for loop and exclude the caller

local players = game:GetService('Players')

OnServerEvent:Connect(function(player, ...)

  for _, v in ipairs(players:GetPlayers()) do
    if v ~= player then
      remote:FireClient(v, ...)

Should work in theory

Alright ill get back to you in a bit, taking a small break to eat

Alright set up some code for replication and got the base code set up in the gun

Althought now not sure how to create the “Laser”

Also whats a good place to store settings for a player? Like checking if the player has other player’s bullets on or off, where would i store this?

Code

Server

local Tool = script.Parent
local Event = Tool.MainEvent
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {}
Params.FilterType = Enum.RaycastFilterType.Blacklist

local function OnEquipped()
	local C = {}
	local Holder = Tool.Parent
	table.insert(C, Holder)
	for i, v in ipairs(workspace.Ignored:GetChildren()) do
		table.insert(C, v)
	end
	Params.FilterDescendantsInstances = C
end

local function Shoot(Player, ray)	
	local Rv = ray.Direction * 300
	local Raycast = workspace:Raycast(ray.Origin, Rv, Params)
	
	local HitPos = if Raycast then Raycast.Position else ray.Origin + Rv
	
	local ShootFrom = Tool.Handle.Attachment.WorldPosition
	
	local AimAt = HitPos - ShootFrom
	local HitDetection = workspace:Raycast(ShootFrom, AimAt * 2, Params)
	
	local ThingHit = if HitDetection then HitDetection.Instance else nil
	
	local PosHit = if HitDetection then HitDetection.Position else HitPos
	
	if ThingHit then
		print(ThingHit)
	end
	
	for i, v in ipairs(game.Players:GetPlayers()) do
		if v ~= Player and v then
			Event:FireClient(v, "WhatEverDataINeedToSendToCreateTheBullet"))
		end
	end
end



Event.OnServerEvent:Connect(Shoot)
Tool.Equipped:Connect(OnEquipped)

Client

local Tool = script.Parent
local player = game.Players.LocalPlayer
local UIS = game:GetService("UserInputService")
local Event = Tool:WaitForChild("MainEvent")

local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {}
Params.FilterType = Enum.RaycastFilterType.Blacklist


local function OnEquipped()
	local C = {}
	local Holder = Tool.Parent
	table.insert(C, Holder)
	for i, v in ipairs(workspace.Ignored:GetChildren()) do
		table.insert(C, v)
	end
	Params.FilterDescendantsInstances = C
end

local function BulletGen(ray)
	local Rv = ray.Direction * 300
	local Raycast = workspace:Raycast(ray.Origin, Rv, Params)

	local HitPos = if Raycast then Raycast.Position else ray.Origin + Rv

	local ShootFrom = Tool.Handle.Attachment.WorldPosition

	local AimAt = HitPos - ShootFrom
	local HitDetection = workspace:Raycast(ShootFrom, AimAt * 2, Params)

	local ThingHit = if HitDetection then HitDetection.Instance else nil

	local PosHit = if HitDetection then HitDetection.Position else HitPos

	if ThingHit then
		print(ThingHit)
	end
end

local function ClientBullet()
	
end

script.Parent.Activated:Connect(function()
	local mouse = UIS:GetMouseLocation()
	local ray = workspace.CurrentCamera:ViewportPointToRay(mouse.X, mouse.Y)
	Event:FireServer(ray)
	BulletGen(ray)
end)

script.Parent.Equipped:Connect(OnEquipped)
Event.OnClientEvent:Connect(ClientBullet)

I am just repeating myself at this point. You have the demo I sent and you can always just go in and have a look
Given two points, find the midpoint with the Lerp function, and then use CFrame.lookAt to orientate the tracer to look at one of the points. Then, set the Z component of the laser’s size to the magnitude of the displacement between the said two points. The X and Y components would be a constant which defines the thickness of the laser

Why should this be a setting? At what point would the player want to hide other player’s tracers in a game that’s all about shooting each other? It would just disadvantage them in the game as then they have no idea who’s shooting at them

You can use attributes to store the gun information. It replicates, so the server can also edit the gun configurations, and the client can make their own private changes to the visual aspects of the gun

Mb, kept forgetting you sent that

I see what you mean here, althougth yes i will do pvp, i was mainly thinking about PvE which wouldn’t really require other peoples bullets to be seen

Anyways i used the tutorial got it to work, although just as one final check theres nothing im doing wrong here?

Server

local Tool = script.Parent
local Event = Tool.MainEvent
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {}
Params.FilterType = Enum.RaycastFilterType.Blacklist

local function OnEquipped()
	local C = {}
	local Holder = Tool.Parent
	table.insert(C, Holder)
	for i, v in ipairs(workspace.Ignored:GetChildren()) do
		table.insert(C, v)
	end
	Params.FilterDescendantsInstances = C
end

local function Shoot(Player, ray)	
	local Rv = ray.Direction * 300
	local Raycast = workspace:Raycast(ray.Origin, Rv, Params)
	
	local HitPos = if Raycast then Raycast.Position else ray.Origin + Rv
	
	local ShootFrom = Tool.Handle.Attachment.WorldPosition
	
	local AimAt = HitPos - ShootFrom
	local HitDetection = workspace:Raycast(ShootFrom, AimAt * 2, Params)
	
	local ThingHit = if HitDetection then HitDetection.Instance else nil
	
	local PosHit = if HitDetection then HitDetection.Position else HitPos
	
	if ThingHit then
		print(ThingHit)
	end
	
	for i, v in ipairs(game.Players:GetPlayers()) do
		if v ~= Player and v then
			Event:FireClient(ShootFrom, PosHit)
		end
	end
end



Event.OnServerEvent:Connect(Shoot)
Tool.Equipped:Connect(OnEquipped)

Client

local Tool = script.Parent
local player = game.Players.LocalPlayer
local UIS = game:GetService("UserInputService")
local Event = Tool:WaitForChild("MainEvent")
local Bullet = workspace.Ignored.ClientBullet
local Debris = game:GetService("Debris")

-- For Easier Changing --
local BulletSize = 0.2
local BulletColor = Color3.new(1,1,0)
local RayLength = 300
-------------------------

local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {}
Params.FilterType = Enum.RaycastFilterType.Blacklist


local function OnEquipped()
	local C = {}
	local Holder = Tool.Parent
	table.insert(C, Holder)
	for i, v in ipairs(workspace.Ignored:GetChildren()) do
		table.insert(C, v)
	end
	Params.FilterDescendantsInstances = C
end

local function BulletGen(ray)
	local Rv = ray.Direction * RayLength
	local Raycast = workspace:Raycast(ray.Origin, Rv, Params)

	local HitPos = if Raycast then Raycast.Position else ray.Origin + Rv

	local ShootFrom = Tool.Handle.Attachment.WorldPosition

	local AimAt = HitPos - ShootFrom
	local HitDetection = workspace:Raycast(ShootFrom, AimAt * 2, Params)

	local ThingHit = if HitDetection then HitDetection.Instance else nil

	local PosHit = if HitDetection then HitDetection.Position else HitPos
	
	local D = Bullet:Clone()
	D.Color = BulletColor
	D.Size = Vector3.new(BulletSize, BulletSize, (ShootFrom - PosHit).Magnitude)
	D.CFrame = CFrame.lookAt(ShootFrom:Lerp(PosHit, .5), PosHit)
	D.Parent = workspace.Ignored
	Debris:AddItem(D, .2)
end

local function ClientBullet(From, To)
	local ReplicatedBullet = Bullet:Clone()
	ReplicatedBullet.Color = BulletColor
	ReplicatedBullet.Size = Vector3.new(BulletSize, BulletSize, (From - To).Magnitude)
	ReplicatedBullet.CFrame = CFrame.lookAt(From:Lerp(To, .5), To)
	ReplicatedBullet.Parent = workspace.Ignored
	Debris:AddItem(ReplicatedBullet, .2)
end

script.Parent.Activated:Connect(function()
	local mouse = UIS:GetMouseLocation()
	local ray = workspace.CurrentCamera:ViewportPointToRay(mouse.X, mouse.Y)
	Event:FireServer(ray)
	BulletGen(ray)
end)

script.Parent.Equipped:Connect(OnEquipped)
Event.OnClientEvent:Connect(ClientBullet)

I would suggest that you make the raycast rays longer, maybe at least 1 thousand given the size of the map for both raycasts (camera hit and hitreg)

This could definitely be simplified if you include Holder inside the table constructor:

local C = {Tool.Parent}

Other than that, everything seems fine from just looking at it