Hello, I am scripting gun, it works perfectly fine, but hit detection is really horrible and almost impossible to kill player with it. Is there any way to improve hit detection for my ray gun?
--/// Variables \\\--
local remote = script.Parent.ServerEvent
local configuration = script.Parent.Configuration
--/// Functions \\\--
remote.OnServerEvent:Connect(function(Player, FromP, ToP, plr)
configuration.CurrentAmmo.Value = configuration.CurrentAmmo.Value - 1
if configuration.Equipped.Value == true then
script.Parent.Output.FireSound:Play()
script.Parent.Output.ParticleEmitterFX.Enabled = true
wait(0.02)
script.Parent.Output.ShootLightFX.Enabled = true
script.Parent.Output.PointLightFX.Enabled = true
script.Parent.Output.SmokeFX.Enabled = true
wait(0.08)
script.Parent.Output.ParticleEmitterFX.Enabled = false
wait(0.02)
script.Parent.Output.ShootLightFX.Enabled = false
script.Parent.Output.PointLightFX.Enabled = false
script.Parent.Output.SmokeFX.Enabled = false
end
local RayCast = Ray.new(FromP,(ToP-FromP).unit*100)
local Part,Position,Normal = game.Workspace:FindPartOnRay(RayCast,Player.Character, false,true)
local Dist = (ToP-FromP).magnitude
if not Dist then
Dist = 300
end
local Lazer = Instance.new("Part")
Lazer.Parent = game.Workspace
Lazer.Anchored = true
Lazer.CanCollide = false
Lazer.Transparency = 0.9
Lazer.BrickColor = game.Teams[script.Parent.Configuration.Team.Value].TeamColor
Lazer.Size = Vector3.new(0.1,0.1,Dist)
Lazer.CFrame = CFrame.new(FromP,Position)*CFrame.new(0,0,-Dist/2)
local Hole = game.ReplicatedStorage.Hole:Clone()
if Part then
Hole.Parent = Part.Parent
end
Hole.Position = ToP
Hole.CFrame = CFrame.new(Hole.Position, Hole.Position+Normal)
if Hole then
wait(0.02)
local HoleBounce = script.HoleBounceFireEffect:Clone()
HoleBounce.Parent = Hole
HoleBounce.Enabled = true
wait(0.2)
HoleBounce.Enabled = false
end
if Hole then
wait(0.02)
local HoleBounce = script.HoleBounceDustEffect:Clone()
HoleBounce.Parent = Hole
HoleBounce.Enabled = true
wait(0.3)
HoleBounce.Enabled = false
end
game.Debris:AddItem(Lazer,0.2)
if Part then
if Part.Parent then
if Part.Parent:FindFirstChild("Humanoid") then
if game.Players:FindFirstChild(Part.Parent.Name) then
if game.Players[plr.Name].TeamColor == game.Players[Part.Parent.Name].TeamColor then
-- Do not take any damage
else
if plr.Name == Part.Parent.Name then
-- Do not take any damage
else
Part.Parent.Humanoid:TakeDamage(configuration.Damage.Value)
end
end
end
end
end
end
game.Debris:AddItem(Hole,1)
end)
--/// logic \\\--
First things first, do the effects like muzzle flash and ray rendering on the client. Second off, you might be having bad hit detection due to the waits you added at the beginning of the event in the first if statement. That would make it yield for a couple fractions of a second making the shot appear delayed. The muzzle flash and ray should be rendered on your client and then on all the other clients separately. Doing so should help you out assuming i read it correctly.
There are quiet a few things I see as an issue here, I’d just like to point out that you should be doing server sided checks on ammo values and such. Along with what Kinko said about using the client for visuals; The clip down below has visuals display client sided by using FireAllClients() and passing values such as possibly the player shooting, because I’ve found that if you do the start position that is sent from the server it may appear like it doesn’t come straight out of the barrel of the gun. Muzzle flash and sound would be easily more manageable if you simply Played/Enabled them when you were rendering the bullet. https://gyazo.com/8c3412fa66e8c5d0cdfca72c79aa6c32
As what others have said, hit detection will only be instant if you do raycasting, muzzle flash and sounds on the client. You can send this information to the server later, but I recommend having tracers, flashes and sounds fired to all other clients, rather than the server. Otherwise you’ll have double sounds for the client firing the gun. Also, I highly recommend using spawn(function() or coroutines when enabling the muzzle flash so the rest of the code runs while the muzzle flash is enabling/disabling.
This is the age long dance between security and usability - what you’re experiencing here is a lag between the server and client (this is inevitable if you run this operation server-side)
Not everything is better on the server - this can cause lag issues and also is not necessarily more secure.
Whilst I’d like to go on about it entirely myself, there is a Developer Hub article which explains it far better than I could hope to do - you can find it here: (Client-Server Model Article)
To summarize it though:
This is the layout of a Roblox Network:
You want to keep traffic between Server <-> Clients to a minimal (to maintain minimum latency and bandwidth usage)
Keeping this in mind, you should in general:
Put visual / feedback / user input on the client normally. Doesn’t matter if they exploit what they see.
Make up with the sacrifice in security you have just made with server validation.
However you also should never trust client inputs
In particular with guns, there isn’t really any “perfect” solution - all solutions will either have to trust the client a bit, or be difficult to use / intensive on the server. Just work out what is required for your game and work on that basis.
To add on this, Valve has made an article on compensating for latency, as they handle hit detection on the server. However, this is a lot of work to be done to be made efficient, and ROBLOX’s network system isn’t all too fast.