Continuing from this thread, I’ve realized that hitboxes on the server may be heavily affecting the smoothness of gameplay. I had know that making hitboxes on the client would be better than on the server, but I thought that the difference would be negligible. But now at the current state of my game, I’m thinking that making hitboxes on the server may be massively taking away from the smoothness of my game. Does anyone know how much of an improvement hitboxes on the client would be over the server? I believe hitboxes are the main reason for my games very choppy and janky combat, but it could be something else. I’m just assuming its the hitboxes due to how unresponsive it feels to play with.
Hello! Yes, Hitboxes on the client are smoother than the server.
But, there is alot more then what is on the surface, I will go over it under this.
Hitbox Information
Main Information:
-
Hitbox Creation Method? Ex: Part, SpatialQuery, GetPartsInPart.
-
Hitbox Call Method? Ex: Clone Part And Make It A Hitbox, Instance.New() , Spatial Query.
-
Hitbox Detection Method? Ex: Runservice, Connection, Function.
-
Hitbox Replication Method? Ex: Replicate To All clients, Distribute From Server.
-
Hitbox Destruction Method? Ex: DebrisService, Destroy(), Timer.
Other Information:
-
Hitbox Frequency? Ex: 1 Swing 1 Hitbox , 2 Swings 4 Hitboxes.
-
Hitbox Size? Ex: Size Of Character, Size Of The Room.
-
Hitbox Shape? Ex: Box, Sphere, Circular.
-
Hitbox Math? Ex:
(RootPart.Position - EnemyRootPart.Position) .Magnitude <= Size.Z +8 then
-
Hitbox Logic? Ex: Spatial Query Math.
These Are All Factors That Should Go Into Deciding How To Do Hitboxes.
Reasons To Use Client
-
All Math, Logic, Creation, Deletion, And Load will all or mostly be on the client, therefore Much Better Performance
-
More Accurate Hitboxes
-
Better Response Input and Output
-
Replication Is automatic or very easy
-
Easier to work with for implementing unique features
-
Almost or nearly no hitbox related bugs because of performance
Reasons To Use Server
-
Better Exploit Checks
-
Easier time coding logic
-
Methods that are very useful (Only on server)
-
Hit Detection is more truthful (Less false positives)
Do you know if it would be fine to use a remote function from the server to the client to create a hitbox on the client? Like lets say im doing this with m1s, would it be better to use the remote function or just create the hitbox before firing to the server
That would be ok in terms of performance.
But, Exploiters can infinitely yield RemoteFunctions, BindableFunctions/Events On the server.
RemoteEvents or UnreliableEvents would be a better use here.
As well as any networking module
well that definitely complicates things. This would require me to change alot, but now that makes a concern of how I would handle delayed skill hitboxes. Like lets say I have an ability that has a short windup and then a hitbox, I currently would just wait on the server and then activate the hitbox, but if I do that on the client then exploiters can just remove the wait. In fact this pretty much applies to every hitbox, as every hitbox I have has a short windup, including m1s. Id love to pick apart a game that actually has functional hitboxes, as this is incredibly confusing. I don’t see a way of doing this without making it exploitable.
why don’t you just create the hitbox on the server and connect it to the character?
What do you mean connect? If you mean filtering with spatial queries like overlap params, then I’m already doing that.
define hitbox
What makes server-sided hitboxes feel bad is because of two things: The discrepency between where you character is on your computer and where it is on the server, and the fact that the server will only detect targets on the server.
To clarify on that last part, it’s basically like if you throw a projectile, but instead of aiming for them on your screen, you have to guess where they are on the server instead.
Relevant guide here.
Here’s one of my hitbox functions:
function module:AOEhitbox(Char:Model, size:Vector3, cframe:CFrame, showHitboxes:boolean, ignoreRagdoll:boolean,ignoreImmune:boolean)
local filterObjects = {}
local hitlist = {}
local maxObjectsAllowed = 10
local params = OverlapParams.new(filterObjects,Enum.RaycastFilterType.Exclude,maxObjectsAllowed,"Default")
params.FilterDescendantsInstances = {Char}
local objectsInSpace = workspace:GetPartBoundsInBox(cframe,size,params)
if showHitboxes then
local part = Instance.new("Part")
part.Size = size
part.CFrame = cframe
part.Anchored = true
part.CanCollide = false
part.Parent = workspace
part.Transparency = 0.5
part.Material = Enum.Material.Neon
part.Color = Color3.new(1, 0, 0)
task.spawn(function()
task.wait(1)
part:Destroy()
end)
end
local checkedTable = {}
local last = nil
for i, v in pairs(objectsInSpace) do
if v.Parent:IsA("Model") then
local model = v.Parent
if model:FindFirstChild("Humanoid") and model ~= last and table.find(checkedTable, model) == nil then
table.insert(checkedTable, model)
local hitChar = getCharacter(model)
if hitChar then
local immune = (#hitChar:GetAllActiveStatusEffectsOfType(Immune) >= 1)
local rag = (#hitChar:GetAllActiveStatusEffectsOfType(Ragdoll) >= 1)
if ignoreRagdoll then
rag = false
end
if ignoreImmune then
immune = false
end
if model.Humanoid.Health > 0 and (not immune) and (not rag) then
table.insert(hitlist, model)
last = model
end
end
end
end
end
return hitlist
end
by hitbox im referring to any spatial query used to detect players within a specified area. I use gerpartsinboundbox or getpartsinpart
Oh, because I thought you were saying hitbox as in the actual collision box around the players. But if you’re meaning the hit detection system then yeah definitely on the client is better by a ton. It will basically eliminate any latency and will have a hugely noticeable difference
Also method wise, it depends on what the ability is tbh. Like sometimes it’s better to use raycast, magnitude or even a proximity prompt. Really depends on the ability
Yeah generally I understand that the client is better, just the issue is that I don’t really get how you would do client sided hitboxes for attacks with delay. The intention is to have the hitbox made before firing to the server, but what if you need to delay the attack by a bit before activating the hitbox. You can’t really do client sided hitboxes if you fire to the server, delay, and then get the hitbox on the client.
I’d imagine this would look something like:
--Client
remoteEvent:FireServer()
--Server
task.wait(1)
local hits = remoteFunction:InvokeClient(player)
Thats how I would do it, but obviously if your invoking the client thats not super smooth either, so the other idea would be:
--Client
local hits = hitboxFunction(size,cframe,etc)
remoteEvent:FireServer(hits)
--Server
task.wait(1)
for i,v in hits do
v.Humanoid:TakeDamage()
end
And obviously, if theres a delay like that, its gonna look extremely weird if someone who activated an ability somehow hit you if you’ve already moved away from them. So once again, I’m at a loss.
Hitbox check for object on client, send request to server, server checks distance between the hit and the object’s position asynchronously, the damage is registered on server if it is within the radius
Well the thing is, Its almost certainly going to be exploitable.
Networking Issues:
Exploiters control anything on the client, so instead of using simple remote events and what not. use a Network/Signal Module.
This will make it harder for them to figure out and implement hacks.
This will improve network stats
Signal Modules:
GoodSignal
FastSignal
Application
This is probably not optimal. If your going to be waiting. Do it on the client and check it on the server. This solves both problems (Technically)
I can show you how I did it in my game. Its actually quite simple.
There definitely is a way.
The client could just remove the wait though?
That would help alot, thanks
thanks, will use these
I’m also trying to make responsive but safe hitboxes. Could you explain what your approach is exactly?
Because I want my hit boxes to be accurate, the server lag messes everything up when a player is moving at high speeds (i.e. dashing). And then there’s also the lag between using a skill and hitting it (though verbally negligible).
So I should run a hitbox on the client, continue with replicating a hit effect for all clients on the characters that were hit, and then cancel it if the server thinks the players are too far apart?
Or would that look weird if a client calculates a move as hitting another player and then it gets cancelled half a second later?
Hitboxes on the client
Checks on the server
Replication on the client
Should the client wait for the server to check the hitbox before continuing or go on and then stop if the server responds with a different result?
Wait for the server, Its more optimal and going to actually secure your checks
My go to layout is this:
Client → Fires a event to the server which checks if the move can be validated.
Server → Invokes the hitbox from the client with a remote function
Client → Continuing with the remote function the client sends back hit characters which all go through a magnitude sanity check.
(or a custom remote functions since regular remote functions can be exploitable)
Keep in mind this is for hitboxes that are performance heavy like projectiles and this helps with server load and keeps it smooth. You can also use this for melee ofcourse but in some cases you should do hit calculations before firing to the server. Also in some cases its alright to do hitboxes on the server if they are something very simple like raycasts.
So keeping it short. Hit detection on the client, Calculations and sanity checks on the server, Any effects or anything unnecessary to hitboxes on all clients.
Also looking at this message:
It looks very cluttered and time consuming to read. Break it up into modules where you can not only save time in the future but also keep it organized and efficient.
Here are some resources to help you: