Hello. I’m making a gun system from scratch and the hit registration is a bit off.
You need to aim in front of the person you are trying to shoot in order to actually hit them. I realize this is because of delays/ping, and I can’t find any good solution.
Any possible ways to go about this would be appreciated! Note I don’t want to use any libraries such as FastCast, etc.
Also let me know which parts of my scripts (client/server) you need, they might be a bit long to post here.
What are you using for your raycast direction? Mouse.Hit.p? If so try using Mouse.Hit.LookVector
Thank you, let me try this and I’ll get back to you.
Nope, it was wayyyy off. https://gyazo.com/d986acfad623b9550566bbb27941f018 Didn’t even hit the NPCs I was aiming at.
Is there a visible tracer active to see where your bullet is going?
There is not. I can try doing that, but I think it’s an issue with the ping caused by Roblox servers.
I’m only asking because, assuming your raycast origin is the shootPart of the gun and the direction is Mouse.Hit.LookVector, it could be that the raycast is hitting the gun or your character and detecting a hit, but otherwise it could be that LookVector was just not the solution. The Tracer would guide to see what the issue is.
both of those are blacklisted. Also, even then for the shots that would’ve got through, you still have to aim in front of your target (assuming the target is moving) to hit it. Give me a second and I’ll put a tracer on it.
This is using mouse.hit.p
https://gyazo.com/d210823b73c32385b3bd6b41d73bf2f8
This is using lookvector
https://gyazo.com/6578f95ee5bd1fe5e6df833981e63f84
We need to see code in order to see if the raycasting is off or something.
Client Script
local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()
local uip = game:GetService("UserInputService")
local char = plr.CharacterAdded:Wait()
local h = char:WaitForChild("Humanoid")
local draw = h:LoadAnimation(script.Parent.draw)
local shoot = h:LoadAnimation(script.Parent.shoot)
local reload = h:LoadAnimation(script.Parent.reload)
local maxammo = script.Parent.Ammo.Value
plr.CharacterAdded:Connect(function(Char)
char = plr.Character or plr.CharacterAdded:Wait()
end)
script.Parent.Equipped:Connect(function()
local clonedgui = script.Parent:WaitForChild("AmmoCount"):Clone()
clonedgui.Parent = game.Players.LocalPlayer.PlayerGui
mouse.Icon = "http://www.roblox.com/asset/?id=6571262827"
draw:Play()
wait(0.05)
draw:AdjustSpeed(0)
end)
script.Parent.Unequipped:Connect(function()
mouse.Icon = ""
game.Players.LocalPlayer.PlayerGui.AmmoCount:Destroy()
draw:Stop()
end)
script.Parent.Activated:Connect(function()
script.Parent.Fire:FireServer(mouse.Hit.p, true)
plr.PlayerGui:WaitForChild("AmmoCount").count.Text = script.Parent.Ammo.Value .. "/" .. maxammo
local part = Instance.new("Part")
local att = Instance.new("Attachment")
part.Parent = workspace
part.Transparency = 1
part.Anchored = true
part.CanCollide = false
part.Size = Vector3.new(0.001,0.001,0.001)
att.Parent = part
part.Position = mouse.Hit.p
script.Parent.FirePart.Beam.Attachment1 = att
end)
uip.InputBegan:Connect(function(key,gameProcessed)
if key.KeyCode == Enum.KeyCode.R then
script.Parent.Reload:FireServer()
plr.PlayerGui:WaitForChild("AmmoCount").count.Text = maxammo .. "/" .. maxammo
end
end)
script.Parent.HitCheck.OnClientEvent:Connect(function(a)
mouse.Icon = "http://www.roblox.com/asset/?id=6571499887"
wait(0.06)
mouse.Icon = "http://www.roblox.com/asset/?id=6571262827"
end)
Server Script
local fireDistance = 300
local damage = 30
local headshotMultiplier = 1.5
local maxammo = script.Parent.Ammo.Value
script.Parent.Fire.OnServerEvent:Connect(function(player, mousePos)
local raycast = RaycastParams.new()
raycast.FilterDescendantsInstances = {player.Character}
raycast.FilterType = Enum.RaycastFilterType.Blacklist
local result = game.Workspace:Raycast(script.Parent.Handle.Position,(mousePos - script.Parent.Handle.Position)*fireDistance,raycast)
if script.Parent.Ammo.Value > 0 then
script.Parent.Ammo.Value -= 1
local h = player.Character.Humanoid
local shoot = h:LoadAnimation(script.Parent.shoot)
shoot:Play()
if result then
local hit = result.Instance
local model = hit:FindFirstAncestorOfClass("Model")
if model then
if model:FindFirstChild("Humanoid") then
if player.Character.Humanoid.Health > 0 then
if hit.Name == "Head" then
model.Humanoid.Health -= (damage * headshotMultiplier)
else
model.Humanoid.Health -= damage
end
script.Parent.HitCheck:FireClient(player)
end
end
end
end
script.Parent.FirePart.Fire:Play()
script.Parent.FirePart["FlashFX3[Burst]"].Enabled = true
script.Parent.FirePart["FlashFX[Flash]"].Enabled = true
script.Parent.FirePart["FlashFX3[Front]"].Enabled = true
script.Parent.FirePart["FlashFX[Light]"].Enabled = true
wait(0.03)
script.Parent.FirePart["FlashFX3[Burst]"].Enabled = false
script.Parent.FirePart["FlashFX[Flash]"].Enabled = false
script.Parent.FirePart["FlashFX3[Front]"].Enabled = false
script.Parent.FirePart["FlashFX[Light]"].Enabled = false
for i = 1, 5 do
local x = math.random(0,0)/100
local y = math.random(-10,10)/100
local z = math.random(0,0)/100
player.Character.Humanoid.CameraOffset = Vector3.new(x,y,z)
wait()
end
else
script.Parent.FirePart.Click:Play()
end
end)
script.Parent.Reload.OnServerEvent:Connect(function(player)
local h = player.Character.Humanoid
local reload = h:LoadAnimation(script.Parent.reload)
if script.Parent.Reloading.Value == false then
if script.Parent.Ammo.Value < 17 then
script.Parent.Reloading.Value = true
reload:Play()
wait(0.08)
script.Parent.FirePart.MagOut:Play()
wait(1.99)
script.Parent.FirePart.MagIn:Play()
reload.Stopped:wait()
script.Parent.FirePart.Slide:Play()
script.Parent.Ammo.Value = maxammo
script.Parent.Reloading.Value = false
end
end
end)
do the raycast on the client and send the part that was hit
then do another one on the server to check if the hit part is not behind a wall or out of range
Doing this in a localscript returns result as nil:
local raycast = RaycastParams.new()
raycast.FilterDescendantsInstances = {game.Players.LocalPlayer.Character}
raycast.FilterType = Enum.RaycastFilterType.Blacklist
local result = game.Workspace:Raycast(script.Parent.Handle.Position,(mouse.Hit.p - script.Parent.Handle.Position)*fireDistance,raycast)
if it hits something it will return RayResult and if it misses then it will return nil
if RayResult exists then sent RayResult.Instance it to the server
and if it misses or hits a non character just send the position
When I print result on the client, it doesn’t return nil - it returns the raycastresult showing it hit the humanoid. However, when I print it on the server, it returns nil… very confused
EDIT: RaycastResult info is lost when sent from Client to Server, so I passed the result.Instance instead and that worked.