Hit Detection for Attacks?

Questions:

  1. What is bad with .Touched?
    -I heard it’s ‘exploitable’ but if I create the connection on server, what do I need to worry about?

  2. What is optimal detection for ‘AOE’ attacks?
    -I.e, a ground smash
    -Magnitude, GetPartsInPart …?

  1. I would highly not recommend using .Touched as hitbox. I used it before and it sucked in my opinion.

  2. You can use Region3 but Magnitude does well at detecting all players within a range.

What did you find that ‘sucked’ with Touched?

It’s just not ideal in my opinion. For hitbox I’d recommend using Region3 or RaycastHitboxV4 which is made specifically for melees.

I’m probably being biased about .Touched not being good but I’ve also seen people having a terrible experience with it: Do you think a .Touched event is better than Raycasting for combat style games? - #4 by dynomatree

For normal hitboxes I recommend overlap params (but then again raycasting might work better if you’re using weapons like swords). For AOE magnitude is good unless you have 50+ players in which case you should use overlap params again so you don’t have to go through every character in a loop and check the magnitude.

Why I don’t recommend .Touched

  1. As far as I recall, .Touched require parts to be instantiated on the client for the signal to fire. If you go into a new Roblox place, create a simple brick with the script:
game.Workspace.Part.Touched:Connect(function(hit)
	local h = hit.Parent:FindFirstChild("Humanoid")
	if h then
		h:TakeDamage(1)
	end
end)

Playtest and run the place. Delete the part locally for the client whilst it’s still there on the server. From the server view, even when the player is clipping through the part, the hits fail to register. This really isn’t a desirable behaviour.

  1. .Touched also fires on a per-bodypart basis, which means you’ll get different results depending on which bodyparts are in the hitbox radius. You can get around this issue with debounce tables or other methods. Queries allow you to more intelligently filter these results.

  2. .Touched has an unpredictable behaviour. If you create a hitbox and a player remains inside it for several seconds, how many times do you want .Touched to fire? Do you want them walking around in the hitbox region to make a difference? .Touched is undesirably hard to predict and the same situation will feel like it produces different results.

  3. Arguably most importantly, .Touched requires a live part to be created. All the hitbox geometry, rendering, replication, etc must be dealt with. Each hitbox is replicating a live part to clients, which are in turn simulating the physics of said hitboxes. 60 Spatial queries a second? Easy. 60 Hitboxes created per second, all creating TouchInterests? Not so easy.


AoE Attacks
Magnitude is the most computationally efficient method I can think of (despite the square roots!) but it has a few drawbacks. You’ll likely find yourself measuring the magnitude from the centre of the AoE to the HumanoidRootPart which oftentimes feels inaccurate. This is especially an issue for AoEs with a small diameter as the difference feels noticable.

I personally prefer to use WorldRoot:GetPartBoundsInRadius() . If you have some simple constructor for overlapParams that whitelists player bodyparts only, this method seems quite effective.

I hope these thoughts are useful for you. :slight_smile:

I personally use spatial query for all my combat including skills, m1s and all that (GetPartBoundsInBox(), GetPartBoundsInRadius(), GetPartsInPart(), etc). They each have their own use cases. For AOE attacks I’d recommend getpartboundsinradius for things like an explosion. I prefer these over magnitude because you don’t have to constantly loop through entities / characters to compare distances. If you want uber precise m1 hitboxes though then you can probably look into something like RaycastHitboxV4, but for AOES spatial query should suit you fine.

Thanks for the helpful response.

Regarding .Touched, from your response I believe the only ‘exploit’ concerns are players deleting the part/touchinterest on their client to prevent themselves from getting hurt/detected by that part?

And nothing else, i.e a player can’t move a damaging-part on their client (that was made on the server) to another player to damage that player? (I could be wrong but shouldn’t this be impossible because it was done on the client and not on server, or is this possible?)

Outside of players being given NetworkOwnership of hitboxes, I can’t think of any standard circumstances where players could maliciously CFrame parts to other players and have those changes replicated on the server.

I do think the primary exploit for .Touched is deletion rather than moving hitboxes, so your understanding sounds correct to me.

Touched may not register hits that are done way too close to player, due to part being inside of the hitbox before hit was started, it makes large swords very uncomfortable to use. Touched is also in full control of exploiters, they can fire it to hit other players and completely ignore themselves (kind of).

  1. Any client-side hit detection is exploitable. However, it is generally agreed upon that the benefits client-side hit detection outweight the vunerabilities. You can primarily counter exploiters by checking if an attack was in reasonable range to hit, such as a magnitude check to see if the distance between attacker and target is less than 10 studs.
client_hit_person.OnServerEvent:Connect(function(player,target)
	if (player.Character.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude < 10 then
		--//hit
	else
		print("nuh uh")
	end
end)
  1. Unless you have a game with hundreds of targets, magnitude is better for simple, spherical attacks.
1 Like