Hitbox Issues for High Velocity Parts

Im making a soccer game and For my game hitbox, Im using a Square Part welded to my player character and inside of it , there is script that have a touched function that detect The ball whenever its touching the Hitbox

its working fine but Now the Issue that is annoying me is that there is a delay when the Goalkeeper want to catch the ball that is moving at high velocity

the hitbox is reacting Way too slow that the ball enter the net before the hitbox does anything

Now im wondering what is the best hitbox for stuff like that, idk if touched is the best way to be honest

Im thinking to make the hitbox client side but i guess it will be easy to exploit. What do you guys think?

2 Likes

I’d look into using this. It returns a list of parts, but if you limit the maximum amount returned to just 1 and apply a filter to only check for the soccerball, a simple check to see if they’re touching can be like this:

-- Beginning of the script somewhere
local Hitbox = -- Put it here.
local Ball = -- Soccer Ball here.

local OP = OverlapParams.new()
OP.MaxParts = 1
OP.FilterType = Enum.RaycastFilterType.Include
OP.FilterDescendantsInstances = {Ball}

-- Later in the script
local BallFound = workspace:GetPartsInPart(Hitbox, OP)
if (BallFound) then
     local SoccerBall = BallFound[1] -- It will always be the first thing in the list
end

From my experience I’ve found this to be way better and consistent than .Touched. In reality, you should probably never use touch and always opt to use something better.

I’m sure there’s plenty of ways to do hitboxes, (and I’m not even sure if this is super performant or the best way) but this should work well.

1 Like

I assume i have to use a loop to make the hitbox always check if a ball is inside of it ?

not sure if this is performant with many players playing.

1 Like

you could try using a raycast or a shapecast (idk wth that is tbh but if its what it sounds like then thats probably what you need)

also shoudn’t this go in script help place?

I’m not sure what your goal is performance-wise but a potentially faster method for detecting if the ball is where it needs to be is to check its magnitude frame by frame on the server and if its a set distance register it as a “hit”. I would recommend playing around with this idea first to make sure it works as I have not actually done something like that.

you could improve performance and only perform the check when the ball gets kicked and is expected to hit the net or goalkeeper.

1 Like

Yes, you would need a loop. There’s a lot of ways to optimize it, and some that I can think of would be doing everyone all at once in a single heartbeat on the server (I do this in a lot of my games). This way you don’t have individual loops running all doing the same thing, rather just one big one that handles all of the players. Once every frame or every other frame is sufficient and shouldn’t stress the game.

To make it more performant, make sure your hitboxes have everything physics related turned off besides CanQuery. Only scan for the ball if the soccerball is x amount of studs from the character. If you’re doing this radius check, make it large to accommodate those high-velocity scenarios. 30 Studs would be a good distance to continuously check for parts. Since you’re only using spatial queries on 2 parts at a time (the hitbox and the ball) it’s already pretty performant of a check.

Depending on your game, you might only want to check for touches at certain times within a game. Make sure to keep that in mind and use it to your advantage for more performance.

4 Likes

I will try your solution tommorow, But one thing, How can i make one single loop that check for All Players hitbox, Should I add the hitboxes into an array and make the loop check for every hitbox in that array?

If you use normal characters it’s not too hard.

-- In your server script
local RS = game:GetService("RunService")
local Characters = {}

-- Use Player Added / Leaving Events to insert their characters into the table.
--[[ Example:
game.Players.PlayerAdded:Connect(function(player)
      player.CharacterAdded:Connect(function(char)
             table.insert(Characters, char)
      end)
end)
]]

RS.Heartbeat:Connect(function(dt)
      for i, Character in pairs(Characters) do
      end
end)

You can use the modulus operator (%) to run checks at a slower rate, i.e every other frame.

2 Likes

ok so I tried it, and it only work if the ball is not moving, if the ball is moving at high speed, its dosent even react to it, touched event was working better but it had a delay

im confused , what is wrong ? im really lost on what should i use for hitbox at this point :confused:

Could I see your code for your loop? Maybe there are some improvements to make. If spatial queries don’t work out, I’d definitely give magnitude checks a try instead like @mantorok4866 suggested.

I actually found a way to fix this issue, I decided to make only the gk mechanics client side (which reduce the delay a little bit) but there is still a small delay and the ball will go inside the net before the hitbox react, so what i did, i made the net goal detection wait 1 second and check again if the ball is still inside, this way if there is delay, it will not count it as a goal, and if the gk actually didn’t catch the ball, the ball will stay inside for at least 1 second , which means its a goal

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.