With my FPS, if you shoot someone, they “die” on your client, and it sends a remote event to server, to allow for double checking. However, even with this client kill, there’s still such a large delay in getting the tag, and said player actually dying.
When I get the kill, their character kind of freezes, however their waist still keeps moving, and then they “die” (on the server) after 1-2 seconds. Worth noting, I am using a ragdoll system. But even without the ragdoll system, the character just freezes, and then dies 1-2 seconds later. This is causing countless problems for UX, as there’s no fast, fluid reaction to your tag, as the player (who on your screen you tagged) is still moving around for a couple of seconds.
So how can I get the death on your screen instant? I understand exploiters could go around getting kills on their screen, but I am still doing server side checks anyway. There’s countless games on Roblox that have instant kills when you get a tag.
if HitCharacter then
if not HitCharacter:FindFirstChild("Humanoid") then -- HitPart could be part of gun or hitbox
HitCharacter = HitCharacter.Parent
if HitCharacter:FindFirstChild("Humanoid") then -- Character found
CharacterFound = true
end
else -- HitPart was most likely a body part
CharacterFound = true
end
if CharacterFound then
BulletCache:ReturnPart(bullet) -- Return bullet
local HitPlayer = Players:GetPlayerFromCharacter(HitCharacter)
if HitPlayer then -- Make sure HitPlayer exists
if cast.UserData.Creator == Player then -- Our local player
local Teams = GameSettings:GetAttribute("Teams")
if HitPlayer.Team == Player.Team and Teams then return end -- Can't hit same team member
if HitCharacter:GetAttribute("ForceField") then return end -- Can't tag forcefield player
if HitCharacter.Humanoid.Health <= 0 then return end -- Already dead
if Player.Character.Humanoid.Health <= 0 then return end -- Our player is dead
HitCharacter.Humanoid.Health = 0
TweenHitMarker:Play()
-- Tell server
PlayerHit:FireServer(
HitPlayer,
result.Instance,
result.Position,
cast.UserData
)
HitSound:Play()
Ragdoll.Create(HitPlayer, HitCharacter)
end
end
return -- Don't create splatter
end
end
Is this lag because of your ping? Or is it because of bad script performance. If it’s because of ping, you can ragdoll them on the client as soon as the client says they killed them.
Most games do this actually. In a sense you’ll send over the needed information to the server after verifying on the client and at the same time you’ll (on the client) register the kill. Exploiters will be able to fake deaths but won’t actually get anything out of them.
Besides ping lag, it could be your scripts that are causing huge delays.
These two are what I’m not sure of. You can try quick debug methods, like so:
local a = tick()
-- ragdoll.create() function / whatever function that youre trying to see how fast it runs
print(tick()-a) -- whatever it prints is how long it takes to complete the function
I played it for a bit and I didn’t notice a huge delay, my internet is pretty good though. Nice game.
local A = tick()
HitCharacter.Humanoid.Health = 0
TweenHitMarker:Play()
-- Tell server
PlayerHit:FireServer(
HitPlayer,
result.Instance,
result.Position,
cast.UserData
)
local B = tick()
print("REMOTE EVENT DELAY " .. B - A)
HitSound:Play()
Ragdoll.Create(HitPlayer, HitCharacter)
print("RAGDOLL DELAY " .. tick() - B)
19:59:42.602 REMOTE EVENT DELAY 2.7179718017578e-05 - Client - Bullet:140
19:59:42.606 RAGDOLL DELAY 0.0045022964477539 - Client - Bullet:147
So no real delays with the code?
Cheers
Go to the script that handles this ^ and put the tick() debug method in it. I should’ve been more clear, sorry.
Perhaps your actual server verification takes too long? If you can’t get it any faster you could make the server store the exact tick the kill remote event is received, and after it verifies the kill it will store that kill as legit, and if the target in that remote event kills his killer AFTER the remote event is received by the server, it will look for the first kill and see if it’s valid, and if it is then it will ignore the target’s kill.
It shouldn’t yield tho? I mean here it is anyway
--// Ray hit
local function Hit(player, playerHit, hitInstance, hitPosition, castData)
local A = tick()
if not castData then return end -- No castData sent
if type(castData) ~= "table" then return end -- castData wasn't a table
if not hitInstance then return end
local B = tick()
print("DELAY 1 " .. B - A)
--local Distance = playerHit:DistanceFromCharacter(hitPosition)
--if Distance > MINIMUM_DISTANCE then return end -- Too far away, fake shot
local Bullet = BulletsFired[castData.Id]
--[[
TODO
What if bullet doesn't exist yet?
If close, clients bullet could hit before the server has time to create the bullet,
thus causing a legit tag, but not
--]]
--[[
if not Bullet then -- Bullet does not exist yet, wait for it to possibly exist??
wait(1)
Bullet = BulletsFired[castData.Id]
if not Bullet then return end
end
]]
--print(player.Name, "Bullet found successfully", Bullet, castData.Id)
if player == playerHit then return end -- Creator can't tag themselves
local Teams = GameSettings:GetAttribute("Teams")
if player.Team == playerHit.Team and Teams then return end -- Can't tag your own team
local C = tick()
print("DELAY 2 " .. C - B)
if not player.Character:FindFirstChildWhichIsA("Humanoid") then return end
if player.Character.Humanoid.Health <= 0 then return end -- Firing player is dead
if not playerHit.Character then return end
local D = tick()
print("DELAY 3 " .. D - C)
if playerHit.Character:GetAttribute("ForceField") then return end -- Can't tag forcefield player
local Humanoid = playerHit.Character:FindFirstChildWhichIsA("Humanoid")
if not Humanoid then return end
local E = tick()
print("DELAY 4 " .. E - D)
-- Create all values associated with Creator
local CreatorValue = Instance.new("ObjectValue")
CreatorValue.Name = "Creator"
CreatorValue.Value = player
-- Player's level
local LevelValue = Instance.new("NumberValue")
LevelValue.Name = "Level"
LevelValue.Value = player.PlayerData.Level.Value
LevelValue.Parent = CreatorValue
-- Gun used
local EquippedValue = Instance.new("StringValue")
EquippedValue.Name = "Equipped"
EquippedValue.Value = player.PlayerData.Equipped.Value
EquippedValue.Parent = CreatorValue
-- Get distance
local Distance = (hitPosition - castData.Origin).Magnitude
if Distance >= 200 then -- Longshot
local Longshot = Instance.new("Folder")
Longshot.Name = "Longshot"
Longshot.Parent = CreatorValue
end
if hitInstance.Name == "Head" then -- Headshot
local Headshot = Instance.new("Folder")
Headshot.Name = "Headshot"
Headshot.Parent = CreatorValue
end
CreatorValue.Parent = Humanoid
Humanoid.Health = 0 -- Kill player
end
10:52:10.290 DELAY 1 2.3841857910156e-07 - Server - RaycastManager:45
10:52:10.290 DELAY 2 0.00019264221191406 - Server - RaycastManager:73
10:52:10.290 DELAY 3 8.7738037109375e-05 - Server - RaycastManager:84
10:52:10.290 DELAY 4 8.2969665527344e-05 - Server - RaycastManager:94
So no serious delays?
Yeah no serious delays.
I think the problem is player ping that causes these non-smooth kills. There are ways to do make it seem smoother, like if it’s verified that it’s a kill on the client, it’ll kill them and show that on the client first, then the server will replicate it.
The only downside to that solution is that if your client can create false positives. What I mean by that is if a client kills another player, but the server rejects it (from lag, failed sanity check, etc), the client will see that they killed them but they won’t actually be dead. Not sure how you’d go about fixing that, but odds are it’ll be a rare occurence. If you do implement this, I suggest heavily testing it first in a developer server.
1 Like