Bullet not coming from shootpart when player moving

So, I have been making a raycasting gun recently, but I have run into a problem where the gun won’t shoot from where the shoot part is exactly when the player is moving. I have been researching this issue and it says I should do this on the client, but I don’t know how to do it. I have already tried by making a remote event within the gun and firing it to a local script when the gun fires, but the problem is, it worked, but only one player could see the bullets. I went back to my original code.

Example video:

Code:

Local script:

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local gunhold = character:WaitForChild("Humanoid"):LoadAnimation(game.ReplicatedStorage.GunAnimations.Pistol.Hold)
local reload = character:WaitForChild("Humanoid"):LoadAnimation(game.ReplicatedStorage.GunAnimations.Pistol.Reload)
local mouse = player:GetMouse()
local bulletsleft = script.Parent.Bullets
local inputservice = game:GetService("UserInputService")
local reloading = false
local equipped = false

script.Parent.Equipped:Connect(function()
	equipped = true
	gunhold:Play()
	local cloneofgui = script.Parent.PistolGui:Clone()
	cloneofgui.Parent = player.PlayerGui
	local textlabel = cloneofgui.TextLabel
	textlabel.Text = "Bullets: "..bulletsleft.Value

	bulletsleft.Changed:Connect(function()
		textlabel.Text = "Bullets: "..bulletsleft.Value
	end)
end)	

mouse.Button1Down:Connect(function()
	if equipped then
		local cloneofgui = player.PlayerGui:FindFirstChild("PistolGui")
		local textlabel = cloneofgui.TextLabel
		if bulletsleft.Value > 0 then
			script.Parent.Fire:FireServer(mouse.Hit.p)
			bulletsleft.Value = bulletsleft.Value - 1
			print(bulletsleft.Value)
		elseif bulletsleft.Value == 0 then
			textlabel.Text = "No more bullets! Press R to reload"
			inputservice.InputBegan:Connect(function(input, gameprocessedevent)
				if input.UserInputType == Enum.UserInputType.Keyboard then
					if input.KeyCode == Enum.KeyCode.R then
						if not reloading then
							reloading = true
							textlabel.Text = "Reloading..."
							reload:Play()
							wait(2)
							bulletsleft.Value = 10
							textlabel.Text = "Bullets: "..bulletsleft.Value
							reloading = false
						end
					end
				end
			end)
		end
	else
		--do nothing
	end
end)

inputservice.InputBegan:Connect(function(input, gameprocessedevent)
	if equipped then
		local cloneofgui = player.PlayerGui:FindFirstChild("PistolGui")
		local textlabel = cloneofgui.TextLabel
		if bulletsleft.Value < 10 then
			if input.UserInputType == Enum.UserInputType.Keyboard then
				if input.KeyCode == Enum.KeyCode.R then
					if not reloading then
						reloading = true
						textlabel.Text = "Reloading..."
						reload:Play()
						wait(2)
						bulletsleft.Value = 10
						textlabel.Text = "Bullets: "..bulletsleft.Value	
						reloading = false
					end
				end
			end			
		end
	end
end)	

script.Parent.Unequipped:Connect(function()
	equipped = false
	player.PlayerGui:FindFirstChild("PistolGui"):Destroy()
	gunhold:Stop()
end)

Server script:

local canshoot = true

script.Parent.Fire.OnServerEvent:Connect(function(player, mousepos)
	
	if canshoot then 
		
		canshoot = false
		
		local raycastparams = RaycastParams.new()
		raycastparams.FilterDescendantsInstances = {player.Character}
		raycastparams.FilterType = Enum.RaycastFilterType.Blacklist

		local direction = (mousepos - script.Parent.Shoot.Position).Unit*100
		local raycastresult = game.Workspace:Raycast(script.Parent.Shoot.Position, direction)
		local intersection = raycastresult and raycastresult.Position or script.Parent.Shoot.Position + direction
		local distance = (script.Parent.Shoot.Position - intersection).magnitude
		
		local bullet = game.ServerStorage.Bullet:Clone()
		bullet.Size = Vector3.new(0.1,0.1,distance)
		bullet.CFrame = CFrame.new(script.Parent.Shoot.Position, intersection)*CFrame.new(0,0,-distance/2)
		bullet.Parent = game.Workspace

		if raycastresult then
			local hitpart = raycastresult.Instance
			local model = hitpart:FindFirstAncestorOfClass("Model")

			if model then
				if model:FindFirstChild("Zombie") then
					model.Zombie:TakeDamage(20)
				end
			end
		end

		wait(0.25)
		bullet:Destroy()
		canshoot = true
	end
	
end)

Is it my code?

1 Like

I may be wrong but I think it’s because you’re moving too fast. The bullet part can’t update its position constantly while you’re moving unless you script it yourself to move with the gun. You have already said this yourself.

1 Like

I think this page might help Network Ownership | Roblox Creator Documentation

You need to render the bullet on the client, then tell the server the mouse position to raycast again and verify damage.

I have so stupid solution but i guess it’s only one way to do this:

Shoot position will be futured. Read text after local shootPos that i wrote.

local canshoot = true

script.Parent.Fire.OnServerEvent:Connect(function(player, mousepos)
	
	if canshoot then 
		
		canshoot = false
		
		local raycastparams = RaycastParams.new()
		raycastparams.FilterDescendantsInstances = {player.Character}
		raycastparams.FilterType = Enum.RaycastFilterType.Blacklist
		
		local shootPos = script.Parent.Shoot.Position+(player.Character.HumanoidRootPart.Velocity*0.8) --Just add player velocity (aka. moving direction) and it will shoot bullet where player gonna go in time. I mean, it will shoot from position that in future kinda. Okay you understood. Just copy this script and paste in your.
		local direction = (mousepos - script.Parent.Shoot.Position).Unit*100
		local raycastresult = game.Workspace:Raycast(shootPos, direction)
		local intersection = raycastresult and raycastresult.Position or script.Parent.Shoot.Position + direction
		local distance = (script.Parent.Shoot.Position - intersection).magnitude
		
		local bullet = game.ServerStorage.Bullet:Clone()
		bullet.Size = Vector3.new(0.1,0.1,distance)
		bullet.CFrame = CFrame.new(script.Parent.Shoot.Position, intersection)*CFrame.new(0,0,-distance/2)
		bullet.Parent = game.Workspace

		if raycastresult then
			local hitpart = raycastresult.Instance
			local model = hitpart:FindFirstAncestorOfClass("Model")

			if model then
				if model:FindFirstChild("Zombie") then
					model.Zombie:TakeDamage(20)
				end
			end
		end

		wait(0.25)
		bullet:Destroy()
		canshoot = true
	end
	
end)

Send gif how it works

I tried using it, but Network Ownership only works for unanchored parts. My bullets are anchored when fired.


Still doesn’t work exactly how I want it to.

Yea, but this is the part I am confused on how to do.

try adding the humanoidrootpart’s velocity with the direction

Did this

		local shootpos = script.Parent.Shoot.Position + (player.Character.HumanoidRootPart.Velocity*0.8) 
		local direction = (mousepos - shootpos).Unit*100

Same result.

This is normal. Your “bullet” is actually the trail a bullet would follow. Everything is normal because the trail would not move if the person with the gun moved.

1 Like

How could I make the trail move if the person with the gun moved? :thinking:

I am thinking of shrinking the bullet while the player is moving, but I don’t know how to do that.

But the trail is how the bullet moved through space. If you were shooting a gun, the bullet wouldnt follow you if you shot it.

If you really wanted to, when the trail is created, constantly set it’s position to the barrel of the gun.

1 Like

The client that fires the gun should should be rendering their own bullet first (everything here is visual, do not damage the target). That client will then tell the server that they fired the gun, and the Mouse.Hit.Position.

The server will raycast from the player’s gun muzzle and the given Mouse.Hit.Position. This raycast will then be used for verifying the damage. Then, the server should tell other clients EXCEPT the one who fired the gun the Mouse.Hit.Position to redraw them.

The pseudocode when you handle firing should look a bit like this:

-- In a LocalScript within the gun.
local UIS = game:GetService("UserInputService")
local Remote = [[LOCATION OF REMOTEEVENT]]

local function Fire()
	local MousePosition = Mouse.Hit.Position
	-- Create a ray and visualize it from the gun's muzzle to MousePosition.

	Remote:FireServer(MousePosition)
end

UIS.InputBegan:Connect(function(Input, GPE)
	if not GPE then
		if Input.UserInputType == Enum.UserInputType.MouseButton1 then
			-- Check for conditions before firing.
			Fire()
		end
	end
end)
-- In the server.
local PlayerService = game:GetService("Players")
local Remote = [[LOCATION OF REMOTE]]

Remote.OnServerEvent:Connect(function(Player, MousePosition)
	-- Create a ray from the firing player's gun muzzle to the MousePosition given by the shooter.
	-- Don't visualize this ray.

	-- If the ray hits, damage that humanoid.
	Humanoid:TakeDamage(20)

	-- Regardless if that ray hits or not, we need to send the data to other clients other than the one firing.
	-- So they can visualize it too.
	for _, Client in pairs(PlayerService:GetPlayers()) do
		if Client ~= Player then
			-- Give other clients the information about who fired the gun and where they fired it.
			Remote:FireClient(Player.Name, MousePosition)
		end
	end
end)

-- In another LocalScript within each client, preferably in StarterPlayerScripts.
local PlayerService = game:GetService("Players")
local Remote = [[LOCATION OF REMOTE]]

Remote.OnClientEvent:Connect(function(Name, MousePosition)
	-- Find the player with the name.
	local Shooter = nil
	for _, Client in pairs(PlayerService:GetPlayers()) do
		if Client.Name == Name then
			Shooter = Client
			break
		end
	end

	if Shooter then
		-- Find that player's character and gun muzzle. Might have to use WaitForChild.
		local Character = Shooter.Character
		local Muzzle = Character.Tool.Muzzle

		-- Once we found it, we can visualize everything again.
		-- Raycast from the muzzle to the MousePosition given by the server and then draw it with a part.
	end
end)
4 Likes

So I know this is late, but I don’t know how I can give the other clients the information about who fired the gun so they can visualize the ray too. Any ideas?

My bullets are unanchored when fired. Can you help me use NetworkOwnership to fix the issue?

But what you need to do with bullet, setnetworkowner to nil?