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)
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.
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)
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.
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)
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?